@mcpmesh/sdk 1.4.1 → 2.0.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__/a2a/a2a-bearer.spec.d.ts +2 -0
- package/dist/__tests__/a2a/a2a-bearer.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/a2a-bearer.spec.js +58 -0
- package/dist/__tests__/a2a/a2a-bearer.spec.js.map +1 -0
- package/dist/__tests__/a2a/a2a-client.spec.d.ts +2 -0
- package/dist/__tests__/a2a/a2a-client.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/a2a-client.spec.js +334 -0
- package/dist/__tests__/a2a/a2a-client.spec.js.map +1 -0
- package/dist/__tests__/a2a/a2a-job.spec.d.ts +2 -0
- package/dist/__tests__/a2a/a2a-job.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/a2a-job.spec.js +255 -0
- package/dist/__tests__/a2a/a2a-job.spec.js.map +1 -0
- package/dist/__tests__/a2a/a2a-stream.spec.d.ts +2 -0
- package/dist/__tests__/a2a/a2a-stream.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/a2a-stream.spec.js +278 -0
- package/dist/__tests__/a2a/a2a-stream.spec.js.map +1 -0
- package/dist/__tests__/a2a/agent-a2a-config.spec.d.ts +2 -0
- package/dist/__tests__/a2a/agent-a2a-config.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/agent-a2a-config.spec.js +262 -0
- package/dist/__tests__/a2a/agent-a2a-config.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/auth-filter.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/auth-filter.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/auth-filter.spec.js +127 -0
- package/dist/__tests__/a2a/producer/auth-filter.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/card-builder.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/card-builder.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/card-builder.spec.js +113 -0
- package/dist/__tests__/a2a/producer/card-builder.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/dispatcher.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/dispatcher.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/dispatcher.spec.js +850 -0
- package/dist/__tests__/a2a/producer/dispatcher.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/mount-surface-push.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/mount-surface-push.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/mount-surface-push.spec.js +164 -0
- package/dist/__tests__/a2a/producer/mount-surface-push.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/mount.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/mount.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/mount.spec.js +433 -0
- package/dist/__tests__/a2a/producer/mount.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/public-url-cache.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/public-url-cache.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/public-url-cache.spec.js +116 -0
- package/dist/__tests__/a2a/producer/public-url-cache.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/sse-emitter.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/sse-emitter.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/sse-emitter.spec.js +754 -0
- package/dist/__tests__/a2a/producer/sse-emitter.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/state-translator.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/state-translator.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/state-translator.spec.js +124 -0
- package/dist/__tests__/a2a/producer/state-translator.spec.js.map +1 -0
- package/dist/__tests__/a2a/producer/task-store.spec.d.ts +2 -0
- package/dist/__tests__/a2a/producer/task-store.spec.d.ts.map +1 -0
- package/dist/__tests__/a2a/producer/task-store.spec.js +180 -0
- package/dist/__tests__/a2a/producer/task-store.spec.js.map +1 -0
- package/dist/__tests__/agent-add-tool.spec.d.ts +2 -0
- package/dist/__tests__/agent-add-tool.spec.d.ts.map +1 -0
- package/dist/__tests__/agent-add-tool.spec.js +483 -0
- package/dist/__tests__/agent-add-tool.spec.js.map +1 -0
- package/dist/__tests__/api-runtime-race.spec.d.ts +2 -0
- package/dist/__tests__/api-runtime-race.spec.d.ts.map +1 -0
- package/dist/__tests__/api-runtime-race.spec.js +193 -0
- package/dist/__tests__/api-runtime-race.spec.js.map +1 -0
- package/dist/__tests__/claim-dispatcher.spec.d.ts +2 -0
- package/dist/__tests__/claim-dispatcher.spec.d.ts.map +1 -0
- package/dist/__tests__/claim-dispatcher.spec.js +408 -0
- package/dist/__tests__/claim-dispatcher.spec.js.map +1 -0
- package/dist/__tests__/inbound-job-dispatch.spec.d.ts +2 -0
- package/dist/__tests__/inbound-job-dispatch.spec.d.ts.map +1 -0
- package/dist/__tests__/inbound-job-dispatch.spec.js +185 -0
- package/dist/__tests__/inbound-job-dispatch.spec.js.map +1 -0
- package/dist/__tests__/job-controller-progress.spec.d.ts +2 -0
- package/dist/__tests__/job-controller-progress.spec.d.ts.map +1 -0
- package/dist/__tests__/job-controller-progress.spec.js +85 -0
- package/dist/__tests__/job-controller-progress.spec.js.map +1 -0
- package/dist/__tests__/jobs-cancel-route.spec.d.ts +2 -0
- package/dist/__tests__/jobs-cancel-route.spec.d.ts.map +1 -0
- package/dist/__tests__/jobs-cancel-route.spec.js +88 -0
- package/dist/__tests__/jobs-cancel-route.spec.js.map +1 -0
- package/dist/__tests__/llm-agent-stream.test.d.ts +14 -0
- package/dist/__tests__/llm-agent-stream.test.d.ts.map +1 -0
- package/dist/__tests__/llm-agent-stream.test.js +341 -0
- package/dist/__tests__/llm-agent-stream.test.js.map +1 -0
- package/dist/__tests__/mesh-job-submitter.spec.d.ts +2 -0
- package/dist/__tests__/mesh-job-submitter.spec.d.ts.map +1 -0
- package/dist/__tests__/mesh-job-submitter.spec.js +110 -0
- package/dist/__tests__/mesh-job-submitter.spec.js.map +1 -0
- package/dist/__tests__/proxy-stream.test.d.ts +9 -0
- package/dist/__tests__/proxy-stream.test.d.ts.map +1 -0
- package/dist/__tests__/proxy-stream.test.js +347 -0
- package/dist/__tests__/proxy-stream.test.js.map +1 -0
- package/dist/__tests__/resolver-meshjob.spec.d.ts +26 -0
- package/dist/__tests__/resolver-meshjob.spec.d.ts.map +1 -0
- package/dist/__tests__/resolver-meshjob.spec.js +201 -0
- package/dist/__tests__/resolver-meshjob.spec.js.map +1 -0
- package/dist/__tests__/schema-verdict-policy.test.d.ts +6 -0
- package/dist/__tests__/schema-verdict-policy.test.d.ts.map +1 -0
- package/dist/__tests__/schema-verdict-policy.test.js +126 -0
- package/dist/__tests__/schema-verdict-policy.test.js.map +1 -0
- package/dist/__tests__/sse-stream.test.d.ts +12 -0
- package/dist/__tests__/sse-stream.test.d.ts.map +1 -0
- package/dist/__tests__/sse-stream.test.js +170 -0
- package/dist/__tests__/sse-stream.test.js.map +1 -0
- package/dist/a2a/a2a-bearer.d.ts +27 -0
- package/dist/a2a/a2a-bearer.d.ts.map +1 -0
- package/dist/a2a/a2a-bearer.js +63 -0
- package/dist/a2a/a2a-bearer.js.map +1 -0
- package/dist/a2a/a2a-client.d.ts +114 -0
- package/dist/a2a/a2a-client.d.ts.map +1 -0
- package/dist/a2a/a2a-client.js +405 -0
- package/dist/a2a/a2a-client.js.map +1 -0
- package/dist/a2a/a2a-event.d.ts +25 -0
- package/dist/a2a/a2a-event.d.ts.map +1 -0
- package/dist/a2a/a2a-event.js +9 -0
- package/dist/a2a/a2a-event.js.map +1 -0
- package/dist/a2a/a2a-job.d.ts +58 -0
- package/dist/a2a/a2a-job.d.ts.map +1 -0
- package/dist/a2a/a2a-job.js +264 -0
- package/dist/a2a/a2a-job.js.map +1 -0
- package/dist/a2a/a2a-stream.d.ts +39 -0
- package/dist/a2a/a2a-stream.d.ts.map +1 -0
- package/dist/a2a/a2a-stream.js +290 -0
- package/dist/a2a/a2a-stream.js.map +1 -0
- package/dist/a2a/errors.d.ts +29 -0
- package/dist/a2a/errors.d.ts.map +1 -0
- package/dist/a2a/errors.js +48 -0
- package/dist/a2a/errors.js.map +1 -0
- package/dist/a2a/index.d.ts +12 -0
- package/dist/a2a/index.d.ts.map +1 -0
- package/dist/a2a/index.js +11 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/a2a/producer/auth-filter.d.ts +34 -0
- package/dist/a2a/producer/auth-filter.d.ts.map +1 -0
- package/dist/a2a/producer/auth-filter.js +39 -0
- package/dist/a2a/producer/auth-filter.js.map +1 -0
- package/dist/a2a/producer/card-builder.d.ts +59 -0
- package/dist/a2a/producer/card-builder.d.ts.map +1 -0
- package/dist/a2a/producer/card-builder.js +59 -0
- package/dist/a2a/producer/card-builder.js.map +1 -0
- package/dist/a2a/producer/dispatcher.d.ts +276 -0
- package/dist/a2a/producer/dispatcher.d.ts.map +1 -0
- package/dist/a2a/producer/dispatcher.js +896 -0
- package/dist/a2a/producer/dispatcher.js.map +1 -0
- package/dist/a2a/producer/index.d.ts +26 -0
- package/dist/a2a/producer/index.d.ts.map +1 -0
- package/dist/a2a/producer/index.js +23 -0
- package/dist/a2a/producer/index.js.map +1 -0
- package/dist/a2a/producer/mount.d.ts +75 -0
- package/dist/a2a/producer/mount.d.ts.map +1 -0
- package/dist/a2a/producer/mount.js +422 -0
- package/dist/a2a/producer/mount.js.map +1 -0
- package/dist/a2a/producer/public-url-cache.d.ts +73 -0
- package/dist/a2a/producer/public-url-cache.d.ts.map +1 -0
- package/dist/a2a/producer/public-url-cache.js +0 -0
- package/dist/a2a/producer/public-url-cache.js.map +1 -0
- package/dist/a2a/producer/registry.d.ts +138 -0
- package/dist/a2a/producer/registry.d.ts.map +1 -0
- package/dist/a2a/producer/registry.js +117 -0
- package/dist/a2a/producer/registry.js.map +1 -0
- package/dist/a2a/producer/sse-emitter.d.ts +85 -0
- package/dist/a2a/producer/sse-emitter.d.ts.map +1 -0
- package/dist/a2a/producer/sse-emitter.js +405 -0
- package/dist/a2a/producer/sse-emitter.js.map +1 -0
- package/dist/a2a/producer/state-translator.d.ts +63 -0
- package/dist/a2a/producer/state-translator.d.ts.map +1 -0
- package/dist/a2a/producer/state-translator.js +108 -0
- package/dist/a2a/producer/state-translator.js.map +1 -0
- package/dist/a2a/producer/task-store.d.ts +128 -0
- package/dist/a2a/producer/task-store.d.ts.map +1 -0
- package/dist/a2a/producer/task-store.js +128 -0
- package/dist/a2a/producer/task-store.js.map +1 -0
- package/dist/agent.d.ts +72 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +618 -13
- package/dist/agent.js.map +1 -1
- package/dist/api-runtime.d.ts +25 -0
- package/dist/api-runtime.d.ts.map +1 -1
- package/dist/api-runtime.js +75 -2
- package/dist/api-runtime.js.map +1 -1
- package/dist/claim-dispatcher.d.ts +126 -0
- package/dist/claim-dispatcher.d.ts.map +1 -0
- package/dist/claim-dispatcher.js +478 -0
- package/dist/claim-dispatcher.js.map +1 -0
- package/dist/express.d.ts.map +1 -1
- package/dist/express.js +33 -6
- package/dist/express.js.map +1 -1
- package/dist/inbound-job-dispatch.d.ts +105 -0
- package/dist/inbound-job-dispatch.d.ts.map +1 -0
- package/dist/inbound-job-dispatch.js +335 -0
- package/dist/inbound-job-dispatch.js.map +1 -0
- package/dist/index.d.ts +37 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -3
- package/dist/index.js.map +1 -1
- package/dist/job-context.d.ts +107 -0
- package/dist/job-context.d.ts.map +1 -0
- package/dist/job-context.js +95 -0
- package/dist/job-context.js.map +1 -0
- package/dist/jobs-cancel-route.d.ts +36 -0
- package/dist/jobs-cancel-route.d.ts.map +1 -0
- package/dist/jobs-cancel-route.js +60 -0
- package/dist/jobs-cancel-route.js.map +1 -0
- package/dist/jobs-helper-tools.d.ts +48 -0
- package/dist/jobs-helper-tools.d.ts.map +1 -0
- package/dist/jobs-helper-tools.js +133 -0
- package/dist/jobs-helper-tools.js.map +1 -0
- package/dist/llm-agent.d.ts +62 -53
- package/dist/llm-agent.d.ts.map +1 -1
- package/dist/llm-agent.js +211 -292
- package/dist/llm-agent.js.map +1 -1
- package/dist/llm-provider.d.ts +4 -4
- package/dist/llm.d.ts +4 -1
- package/dist/llm.d.ts.map +1 -1
- package/dist/llm.js +7 -17
- package/dist/llm.js.map +1 -1
- package/dist/mesh-job-submitter.d.ts +83 -0
- package/dist/mesh-job-submitter.d.ts.map +1 -0
- package/dist/mesh-job-submitter.js +143 -0
- package/dist/mesh-job-submitter.js.map +1 -0
- package/dist/proxy.d.ts +30 -0
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +351 -1
- package/dist/proxy.js.map +1 -1
- package/dist/resolver-meshjob.d.ts +170 -0
- package/dist/resolver-meshjob.d.ts.map +1 -0
- package/dist/resolver-meshjob.js +159 -0
- package/dist/resolver-meshjob.js.map +1 -0
- package/dist/route.d.ts +4 -0
- package/dist/route.d.ts.map +1 -1
- package/dist/route.js.map +1 -1
- package/dist/schema-normalize.d.ts +62 -0
- package/dist/schema-normalize.d.ts.map +1 -0
- package/dist/schema-normalize.js +128 -0
- package/dist/schema-normalize.js.map +1 -0
- package/dist/sse-stream.d.ts +44 -0
- package/dist/sse-stream.d.ts.map +1 -0
- package/dist/sse-stream.js +173 -0
- package/dist/sse-stream.js.map +1 -0
- package/dist/types.d.ts +351 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
package/dist/llm-agent.js
CHANGED
|
@@ -4,20 +4,18 @@
|
|
|
4
4
|
* This class handles:
|
|
5
5
|
* - System prompt rendering (with Handlebars templates)
|
|
6
6
|
* - Agentic loop with tool execution
|
|
7
|
-
* - LLM provider calls
|
|
7
|
+
* - LLM provider calls via mesh delegation
|
|
8
8
|
* - Response parsing with Zod validation
|
|
9
9
|
* - Metadata tracking (tokens, latency, tool calls)
|
|
10
10
|
*
|
|
11
11
|
* Configuration Hierarchy (ENV > Config):
|
|
12
|
-
* - MESH_LLM_PROVIDER: Override provider for direct mode (e.g., "claude", "openai", "gemini")
|
|
13
12
|
* - MESH_LLM_MODEL: Override model (e.g., "gpt-4o", "gemini-2.0-flash")
|
|
14
13
|
* - MESH_LLM_MAX_ITERATIONS: Override max agentic loop iterations
|
|
15
|
-
* - MESH_LLM_FILTER_MODE: Override tool filter mode ("all", "include", "exclude")
|
|
16
14
|
*
|
|
17
15
|
* @example
|
|
18
16
|
* ```typescript
|
|
19
17
|
* const agent = new MeshLlmAgent({
|
|
20
|
-
* provider: "claude",
|
|
18
|
+
* provider: { capability: "llm", tags: ["+claude"] },
|
|
21
19
|
* model: "anthropic/claude-sonnet-4-5",
|
|
22
20
|
* systemPrompt: "file://prompts/assistant.hbs",
|
|
23
21
|
* maxIterations: 10,
|
|
@@ -27,6 +25,7 @@
|
|
|
27
25
|
* const result = await agent.run("Help me calculate 2+2", {
|
|
28
26
|
* templateContext: { user: "John" },
|
|
29
27
|
* tools: resolvedToolProxies,
|
|
28
|
+
* meshProvider: { endpoint: "http://provider:9000", functionName: "process_chat" },
|
|
30
29
|
* });
|
|
31
30
|
* ```
|
|
32
31
|
*/
|
|
@@ -35,259 +34,11 @@ import { renderTemplate } from "./template.js";
|
|
|
35
34
|
import { ResponseParser } from "./response-parser.js";
|
|
36
35
|
import { MaxIterationsError, LLMAPIError, ToolExecutionError, } from "./errors.js";
|
|
37
36
|
import { parseSSEResponse } from "./sse.js";
|
|
38
|
-
import { loadProvider, extractVendorFromModel, extractModelName, } from "./llm-provider.js";
|
|
39
|
-
import { ProviderHandlerRegistry } from "./provider-handlers/index.js";
|
|
40
37
|
import { resolveMediaInputs } from "./media/index.js";
|
|
41
|
-
import { getCurrentTraceContext, getCurrentPropagatedHeaders } from "./proxy.js";
|
|
38
|
+
import { getCurrentTraceContext, getCurrentPropagatedHeaders, streamMcpTool, DEFAULT_CALL_OPTIONS, } from "./proxy.js";
|
|
42
39
|
import { generateSpanId, publishTraceSpan, createTraceHeaders, injectTraceContext, } from "./tracing.js";
|
|
43
40
|
import { fetchWithTimeout, isTimeoutError } from "./timeout-utils.js";
|
|
44
41
|
import { getDispatcher } from "./http-pool.js";
|
|
45
|
-
/**
|
|
46
|
-
* Default LiteLLM provider using HTTP proxy.
|
|
47
|
-
* Assumes LiteLLM proxy is running at LITELLM_URL or localhost:4000.
|
|
48
|
-
*/
|
|
49
|
-
export class LiteLLMProvider {
|
|
50
|
-
baseUrl;
|
|
51
|
-
constructor(baseUrl) {
|
|
52
|
-
this.baseUrl = baseUrl || process.env.LITELLM_URL || "http://localhost:4000";
|
|
53
|
-
}
|
|
54
|
-
async complete(model, messages, tools, options) {
|
|
55
|
-
const body = {
|
|
56
|
-
model,
|
|
57
|
-
messages,
|
|
58
|
-
};
|
|
59
|
-
if (tools && tools.length > 0) {
|
|
60
|
-
body.tools = tools;
|
|
61
|
-
body.tool_choice = "auto";
|
|
62
|
-
}
|
|
63
|
-
if (options?.maxOutputTokens)
|
|
64
|
-
body.max_tokens = options.maxOutputTokens;
|
|
65
|
-
if (options?.temperature !== undefined)
|
|
66
|
-
body.temperature = options.temperature;
|
|
67
|
-
if (options?.topP !== undefined)
|
|
68
|
-
body.top_p = options.topP;
|
|
69
|
-
if (options?.stop)
|
|
70
|
-
body.stop = options.stop;
|
|
71
|
-
// Set up timeout (default 300s to match Python SDK's stream_timeout)
|
|
72
|
-
const timeoutMs = parseInt(process.env.LITELLM_TIMEOUT_MS || "300000", 10);
|
|
73
|
-
let response;
|
|
74
|
-
try {
|
|
75
|
-
response = await fetchWithTimeout(`${this.baseUrl}/v1/chat/completions`, {
|
|
76
|
-
method: "POST",
|
|
77
|
-
headers: {
|
|
78
|
-
"Content-Type": "application/json",
|
|
79
|
-
},
|
|
80
|
-
body: JSON.stringify(body),
|
|
81
|
-
timeout: timeoutMs,
|
|
82
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
-
dispatcher: getDispatcher(`${this.baseUrl}/v1/chat/completions`),
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
if (isTimeoutError(error)) {
|
|
88
|
-
throw new LLMAPIError(408, `Request timed out after ${timeoutMs}ms`, "litellm");
|
|
89
|
-
}
|
|
90
|
-
throw new LLMAPIError(0, `Fetch failed: ${error instanceof Error ? error.message : String(error)}`, "litellm");
|
|
91
|
-
}
|
|
92
|
-
if (!response.ok) {
|
|
93
|
-
const error = await response.text();
|
|
94
|
-
throw new LLMAPIError(response.status, error, "litellm");
|
|
95
|
-
}
|
|
96
|
-
return (await response.json());
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Default model mappings for provider shorthand names.
|
|
101
|
-
*/
|
|
102
|
-
const DEFAULT_MODELS = {
|
|
103
|
-
claude: "anthropic/claude-sonnet-4-5",
|
|
104
|
-
openai: "openai/gpt-4o",
|
|
105
|
-
anthropic: "anthropic/claude-sonnet-4-5",
|
|
106
|
-
gemini: "google/gemini-3-flash-preview",
|
|
107
|
-
google: "google/gemini-3-flash-preview",
|
|
108
|
-
gpt4: "openai/gpt-4o",
|
|
109
|
-
gpt35: "openai/gpt-3.5-turbo",
|
|
110
|
-
};
|
|
111
|
-
/**
|
|
112
|
-
* Direct Vercel AI SDK provider.
|
|
113
|
-
* Uses Vercel AI SDK (@ai-sdk/anthropic, @ai-sdk/openai, etc.) directly
|
|
114
|
-
* without needing a proxy server.
|
|
115
|
-
*/
|
|
116
|
-
export class VercelDirectProvider {
|
|
117
|
-
providerSpec;
|
|
118
|
-
cachedProvider = null;
|
|
119
|
-
providerLoadAttempted = false;
|
|
120
|
-
toolProxies = new Map();
|
|
121
|
-
maxSteps = 10;
|
|
122
|
-
constructor(providerSpec) {
|
|
123
|
-
this.providerSpec = providerSpec;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Set tool proxies for execute callbacks in the Vercel AI SDK agentic loop.
|
|
127
|
-
* When set, tools are created with execute callbacks and maxSteps is enabled,
|
|
128
|
-
* letting the SDK handle the tool execution loop internally.
|
|
129
|
-
*/
|
|
130
|
-
setToolProxies(tools, maxIterations) {
|
|
131
|
-
this.toolProxies.clear();
|
|
132
|
-
for (const tool of tools) {
|
|
133
|
-
this.toolProxies.set(tool.name, tool);
|
|
134
|
-
}
|
|
135
|
-
this.maxSteps = maxIterations ?? 10;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Resolve the full model string from provider spec.
|
|
139
|
-
* E.g., "claude" -> "anthropic/claude-sonnet-4-5"
|
|
140
|
-
*/
|
|
141
|
-
resolveModel(model) {
|
|
142
|
-
// If explicit model provided, use it
|
|
143
|
-
if (model && model !== "default") {
|
|
144
|
-
// If model already has vendor prefix, use as-is
|
|
145
|
-
if (model.includes("/")) {
|
|
146
|
-
return model;
|
|
147
|
-
}
|
|
148
|
-
// Otherwise, try to add vendor prefix from provider spec
|
|
149
|
-
const vendor = extractVendorFromModel(DEFAULT_MODELS[this.providerSpec.toLowerCase()] ?? this.providerSpec);
|
|
150
|
-
if (vendor) {
|
|
151
|
-
return `${vendor}/${model}`;
|
|
152
|
-
}
|
|
153
|
-
return model;
|
|
154
|
-
}
|
|
155
|
-
// Map shorthand provider to full model
|
|
156
|
-
const defaultModel = DEFAULT_MODELS[this.providerSpec.toLowerCase()];
|
|
157
|
-
if (defaultModel) {
|
|
158
|
-
return defaultModel;
|
|
159
|
-
}
|
|
160
|
-
// Assume provider spec is already a model identifier
|
|
161
|
-
return this.providerSpec;
|
|
162
|
-
}
|
|
163
|
-
async complete(model, messages, tools, options) {
|
|
164
|
-
const fullModel = this.resolveModel(model);
|
|
165
|
-
const vendor = extractVendorFromModel(fullModel);
|
|
166
|
-
const modelName = extractModelName(fullModel);
|
|
167
|
-
if (!vendor) {
|
|
168
|
-
throw new LLMAPIError(400, `Cannot determine vendor from model: ${fullModel}. Use format "vendor/model" (e.g., "anthropic/claude-sonnet-4-5")`, "vercel");
|
|
169
|
-
}
|
|
170
|
-
// Load provider if not cached
|
|
171
|
-
if (!this.providerLoadAttempted) {
|
|
172
|
-
this.providerLoadAttempted = true;
|
|
173
|
-
this.cachedProvider = await loadProvider(vendor);
|
|
174
|
-
}
|
|
175
|
-
if (!this.cachedProvider) {
|
|
176
|
-
throw new LLMAPIError(500, `Vercel AI SDK provider for '${vendor}' not available. Install: npm install @ai-sdk/${vendor}`, "vercel");
|
|
177
|
-
}
|
|
178
|
-
// Create the model instance
|
|
179
|
-
const aiModel = this.cachedProvider(modelName);
|
|
180
|
-
// Get vendor-specific handler for optimizations
|
|
181
|
-
const handler = ProviderHandlerRegistry.getHandler(vendor);
|
|
182
|
-
// Import generateText from ai package
|
|
183
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
184
|
-
const aiModule = (await import("ai"));
|
|
185
|
-
const generateText = aiModule.generateText;
|
|
186
|
-
const jsonSchema = aiModule.jsonSchema;
|
|
187
|
-
const aiTool = aiModule.tool;
|
|
188
|
-
// Convert tools to Vercel AI SDK format
|
|
189
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
190
|
-
let vercelTools;
|
|
191
|
-
if (tools && tools.length > 0) {
|
|
192
|
-
vercelTools = {};
|
|
193
|
-
for (const tool of tools) {
|
|
194
|
-
const rawSchema = tool.function.parameters ?? {
|
|
195
|
-
type: "object",
|
|
196
|
-
properties: {},
|
|
197
|
-
};
|
|
198
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
199
|
-
const { $schema, ...schemaWithoutMeta } = rawSchema;
|
|
200
|
-
const cleanSchema = {
|
|
201
|
-
type: "object",
|
|
202
|
-
...schemaWithoutMeta,
|
|
203
|
-
};
|
|
204
|
-
const proxy = this.toolProxies.get(tool.function.name);
|
|
205
|
-
vercelTools[tool.function.name] = aiTool({
|
|
206
|
-
description: tool.function.description ?? "",
|
|
207
|
-
inputSchema: jsonSchema(cleanSchema),
|
|
208
|
-
...(proxy ? {
|
|
209
|
-
execute: async (args) => {
|
|
210
|
-
const result = await proxy(args);
|
|
211
|
-
return typeof result === "string" ? result : JSON.stringify(result);
|
|
212
|
-
},
|
|
213
|
-
} : {}),
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
// Apply vendor-specific request preparation
|
|
218
|
-
const preparedRequest = handler.prepareRequest(messages, null, // tools handled separately
|
|
219
|
-
options?.outputSchema ?? null, {
|
|
220
|
-
temperature: options?.temperature,
|
|
221
|
-
maxOutputTokens: options?.maxOutputTokens,
|
|
222
|
-
topP: options?.topP,
|
|
223
|
-
});
|
|
224
|
-
// Build request options
|
|
225
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
226
|
-
const requestOptions = {
|
|
227
|
-
model: aiModel,
|
|
228
|
-
messages: preparedRequest.messages,
|
|
229
|
-
};
|
|
230
|
-
if (vercelTools && Object.keys(vercelTools).length > 0) {
|
|
231
|
-
requestOptions.tools = vercelTools;
|
|
232
|
-
// When tool proxies are set, the SDK handles the agentic loop via execute callbacks.
|
|
233
|
-
// maxSteps allows the SDK to call tools and feed results back to the LLM automatically.
|
|
234
|
-
if (this.toolProxies.size > 0) {
|
|
235
|
-
requestOptions.maxSteps = this.maxSteps;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
if (options?.maxOutputTokens) {
|
|
239
|
-
requestOptions.maxTokens = options.maxOutputTokens;
|
|
240
|
-
}
|
|
241
|
-
if (options?.temperature !== undefined) {
|
|
242
|
-
requestOptions.temperature = options.temperature;
|
|
243
|
-
}
|
|
244
|
-
if (options?.topP !== undefined) {
|
|
245
|
-
requestOptions.topP = options.topP;
|
|
246
|
-
}
|
|
247
|
-
try {
|
|
248
|
-
const result = await generateText(requestOptions);
|
|
249
|
-
// Convert Vercel AI SDK response to LlmCompletionResponse format.
|
|
250
|
-
// When maxSteps is active, the SDK executed tools internally — don't
|
|
251
|
-
// expose intermediate tool_calls to the consumer's outer loop.
|
|
252
|
-
const sdkHandledLoop = requestOptions.maxSteps != null;
|
|
253
|
-
const response = {
|
|
254
|
-
id: `vercel-${Date.now()}`,
|
|
255
|
-
object: "chat.completion",
|
|
256
|
-
created: Math.floor(Date.now() / 1000),
|
|
257
|
-
model: fullModel,
|
|
258
|
-
choices: [
|
|
259
|
-
{
|
|
260
|
-
index: 0,
|
|
261
|
-
message: {
|
|
262
|
-
role: "assistant",
|
|
263
|
-
content: result.text || null,
|
|
264
|
-
tool_calls: sdkHandledLoop ? undefined : result.toolCalls?.map((tc) => ({
|
|
265
|
-
id: tc.toolCallId,
|
|
266
|
-
type: "function",
|
|
267
|
-
function: {
|
|
268
|
-
name: tc.toolName,
|
|
269
|
-
arguments: JSON.stringify(tc.args ?? {}),
|
|
270
|
-
},
|
|
271
|
-
})),
|
|
272
|
-
},
|
|
273
|
-
finish_reason: result.finishReason ?? "stop",
|
|
274
|
-
},
|
|
275
|
-
],
|
|
276
|
-
usage: {
|
|
277
|
-
prompt_tokens: result.usage?.promptTokens ?? 0,
|
|
278
|
-
completion_tokens: result.usage?.completionTokens ?? 0,
|
|
279
|
-
total_tokens: (result.usage?.promptTokens ?? 0) +
|
|
280
|
-
(result.usage?.completionTokens ?? 0),
|
|
281
|
-
},
|
|
282
|
-
};
|
|
283
|
-
return response;
|
|
284
|
-
}
|
|
285
|
-
catch (error) {
|
|
286
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
287
|
-
throw new LLMAPIError(500, `Vercel AI SDK error: ${message}`, "vercel");
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
42
|
/**
|
|
292
43
|
* Mesh provider that delegates to an LLM provider discovered via mesh.
|
|
293
44
|
*/
|
|
@@ -486,6 +237,61 @@ export class MeshDelegatedProvider {
|
|
|
486
237
|
}
|
|
487
238
|
}
|
|
488
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Stream chunks from the mesh-delegated provider's streaming variant.
|
|
242
|
+
*
|
|
243
|
+
* Builds the same ``{request: <MeshLlmRequest>}`` body that ``complete()``
|
|
244
|
+
* produces, then calls the streaming MCP tool via ``streamMcpTool()`` from
|
|
245
|
+
* ``./proxy``. Each ``notifications/progress`` chunk is yielded as a string;
|
|
246
|
+
* the final ``result`` event ends the stream and is NOT yielded (matches the
|
|
247
|
+
* Python ``MeshLlmAgent.stream()`` contract).
|
|
248
|
+
*
|
|
249
|
+
* The provider's ``functionName`` is expected to already be the streaming
|
|
250
|
+
* variant — the registry resolver picks it based on the consumer's
|
|
251
|
+
* ``ai.mcpmesh.stream`` tag opt-in (see ``MeshLlmAgent.stream()``).
|
|
252
|
+
*/
|
|
253
|
+
async *streamComplete(model, messages, tools, options) {
|
|
254
|
+
// Build MeshLlmRequest body — same shape as complete()
|
|
255
|
+
const modelParams = {};
|
|
256
|
+
if (model && model !== "default") {
|
|
257
|
+
modelParams.model = model;
|
|
258
|
+
}
|
|
259
|
+
if (options?.maxOutputTokens)
|
|
260
|
+
modelParams.max_tokens = options.maxOutputTokens;
|
|
261
|
+
if (options?.temperature !== undefined)
|
|
262
|
+
modelParams.temperature = options.temperature;
|
|
263
|
+
if (options?.topP !== undefined)
|
|
264
|
+
modelParams.top_p = options.topP;
|
|
265
|
+
if (options?.stop)
|
|
266
|
+
modelParams.stop = options.stop;
|
|
267
|
+
if (options?.outputSchema) {
|
|
268
|
+
modelParams.output_schema = options.outputSchema.schema;
|
|
269
|
+
modelParams.output_type_name = options.outputSchema.name;
|
|
270
|
+
}
|
|
271
|
+
if (this.parallelToolCalls) {
|
|
272
|
+
modelParams.parallel_tool_calls = true;
|
|
273
|
+
}
|
|
274
|
+
const request = { messages };
|
|
275
|
+
if (Object.keys(modelParams).length > 0) {
|
|
276
|
+
request.model_params = modelParams;
|
|
277
|
+
}
|
|
278
|
+
if (tools && tools.length > 0) {
|
|
279
|
+
request.tools = tools;
|
|
280
|
+
}
|
|
281
|
+
const args = { request };
|
|
282
|
+
// streamMcpTool() handles trace context injection / propagated headers /
|
|
283
|
+
// dispatcher pooling internally — same path as createProxy().stream().
|
|
284
|
+
// Match complete()'s env-backed timeout (MESH_PROVIDER_TIMEOUT_MS) so
|
|
285
|
+
// operators can tune both buffered and streaming provider calls with
|
|
286
|
+
// the same knob. Default 300s (matches Python SDK's stream_timeout).
|
|
287
|
+
const providerTimeoutMs = parseInt(process.env.MESH_PROVIDER_TIMEOUT_MS || "300000", 10);
|
|
288
|
+
const streamOptions = {
|
|
289
|
+
...DEFAULT_CALL_OPTIONS,
|
|
290
|
+
timeout: providerTimeoutMs,
|
|
291
|
+
streamTimeout: providerTimeoutMs,
|
|
292
|
+
};
|
|
293
|
+
yield* streamMcpTool(this.endpoint, this.functionName, args, streamOptions, "mesh-llm-stream");
|
|
294
|
+
}
|
|
489
295
|
}
|
|
490
296
|
/**
|
|
491
297
|
* MeshLlmAgent - The core agentic loop implementation.
|
|
@@ -633,11 +439,6 @@ export class MeshLlmAgent {
|
|
|
633
439
|
// If schema conversion fails, skip
|
|
634
440
|
}
|
|
635
441
|
}
|
|
636
|
-
// Set tool proxies on direct-mode providers so the Vercel AI SDK
|
|
637
|
-
// can execute tools internally via maxSteps (agentic loop in the SDK).
|
|
638
|
-
if (provider instanceof VercelDirectProvider && context.tools.length > 0) {
|
|
639
|
-
provider.setToolProxies(context.tools, this.config.maxIterations);
|
|
640
|
-
}
|
|
641
442
|
// Agentic loop
|
|
642
443
|
let iteration = 0;
|
|
643
444
|
let finalContent = "";
|
|
@@ -731,6 +532,127 @@ export class MeshLlmAgent {
|
|
|
731
532
|
// Parse and validate response
|
|
732
533
|
return this.responseParser.parse(finalContent);
|
|
733
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Stream the final assistant text token-by-token from a mesh-delegated
|
|
537
|
+
* provider's streaming variant (Python's ``@mesh.llm_provider`` auto-
|
|
538
|
+
* generates a ``process_chat_stream`` MCP tool tagged
|
|
539
|
+
* ``ai.mcpmesh.stream``).
|
|
540
|
+
*
|
|
541
|
+
* **Tag opt-in (REQUIRED):** Unlike Python's ``@mesh.llm`` which auto-adds
|
|
542
|
+
* the ``ai.mcpmesh.stream`` tag based on the function's return-type
|
|
543
|
+
* (``Stream[str]`` vs ``str``), TypeScript users must EXPLICITLY include
|
|
544
|
+
* ``"ai.mcpmesh.stream"`` in their provider tag filter to get the
|
|
545
|
+
* streaming variant of the LLM provider:
|
|
546
|
+
*
|
|
547
|
+
* ```ts
|
|
548
|
+
* server.addTool(mesh.llm({
|
|
549
|
+
* name: "chat_stream",
|
|
550
|
+
* provider: { capability: "llm", tags: ["+claude", "ai.mcpmesh.stream"] },
|
|
551
|
+
* // ...
|
|
552
|
+
* execute: async ({ message }, { llm }) => {
|
|
553
|
+
* for await (const chunk of llm.stream(message)) {
|
|
554
|
+
* process.stdout.write(chunk);
|
|
555
|
+
* }
|
|
556
|
+
* return llm.meta?.outputTokens ? "ok" : "no-output";
|
|
557
|
+
* },
|
|
558
|
+
* }));
|
|
559
|
+
* ```
|
|
560
|
+
*
|
|
561
|
+
* Without the ``ai.mcpmesh.stream`` tag the resolver returns the
|
|
562
|
+
* buffered ``process_chat`` tool, and ``stream()`` will yield zero chunks
|
|
563
|
+
* (the buffered tool emits no progress notifications).
|
|
564
|
+
*
|
|
565
|
+
* @param messageInput - User message string or multi-turn message array
|
|
566
|
+
* @param context - Runtime context with tools, mesh provider, and options
|
|
567
|
+
* @returns AsyncIterable yielding text chunks as the provider emits them
|
|
568
|
+
*/
|
|
569
|
+
async *stream(messageInput, context) {
|
|
570
|
+
if (!context.meshProvider) {
|
|
571
|
+
throw new Error("MeshLlmAgent.stream() requires a mesh-delegated provider. " +
|
|
572
|
+
"Configure your agent with provider: { capability: 'llm', tags: ['ai.mcpmesh.stream'] } " +
|
|
573
|
+
"to use a streaming @mesh.llm_provider.");
|
|
574
|
+
}
|
|
575
|
+
// Build the same message list complete()/run() builds (system prompt,
|
|
576
|
+
// multipart media, multi-turn array unwinding) — without the agentic
|
|
577
|
+
// loop. The mesh-delegated streaming provider runs its own loop on the
|
|
578
|
+
// server side and emits text chunks via notifications/progress; the
|
|
579
|
+
// consumer just yields each one.
|
|
580
|
+
const messages = [];
|
|
581
|
+
const isMeshDelegated = true; // by definition: we required meshProvider above
|
|
582
|
+
const toolDefs = this.buildToolDefinitions(context.tools, isMeshDelegated);
|
|
583
|
+
// System prompt with template rendering + tool schema injection.
|
|
584
|
+
// Mirrors run(): mesh-delegated path skips the output-schema hint
|
|
585
|
+
// because the provider applies vendor-specific output formatting.
|
|
586
|
+
const systemPromptTemplate = this.getSystemPrompt();
|
|
587
|
+
if (systemPromptTemplate) {
|
|
588
|
+
let systemContent = await renderTemplate(systemPromptTemplate, context.templateContext ?? {});
|
|
589
|
+
if (toolDefs.length > 0) {
|
|
590
|
+
systemContent += this.buildToolSchemaSection(toolDefs);
|
|
591
|
+
}
|
|
592
|
+
messages.push({ role: "system", content: systemContent });
|
|
593
|
+
}
|
|
594
|
+
// Resolve media items to OpenAI-compatible image_url parts
|
|
595
|
+
const mediaItems = context.options?.media;
|
|
596
|
+
let mediaParts = null;
|
|
597
|
+
if (mediaItems && mediaItems.length > 0) {
|
|
598
|
+
mediaParts = await resolveMediaInputs(mediaItems);
|
|
599
|
+
}
|
|
600
|
+
if (typeof messageInput === "string") {
|
|
601
|
+
if (mediaParts && mediaParts.length > 0) {
|
|
602
|
+
messages.push({
|
|
603
|
+
role: "user",
|
|
604
|
+
content: [
|
|
605
|
+
{ type: "text", text: messageInput },
|
|
606
|
+
...mediaParts,
|
|
607
|
+
],
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
messages.push({ role: "user", content: messageInput });
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
for (let i = 0; i < messageInput.length; i++) {
|
|
616
|
+
const msg = messageInput[i];
|
|
617
|
+
const isLastUser = mediaParts &&
|
|
618
|
+
mediaParts.length > 0 &&
|
|
619
|
+
msg.role === "user" &&
|
|
620
|
+
i === messageInput.length - 1;
|
|
621
|
+
if (isLastUser) {
|
|
622
|
+
messages.push({
|
|
623
|
+
role: "user",
|
|
624
|
+
content: [
|
|
625
|
+
{ type: "text", text: msg.content },
|
|
626
|
+
...mediaParts,
|
|
627
|
+
],
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
messages.push({ role: msg.role, content: msg.content });
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
// Effective options (runtime > env > config)
|
|
636
|
+
const maxTokens = context.options?.maxOutputTokens ?? this.config.maxOutputTokens;
|
|
637
|
+
const temperature = context.options?.temperature ?? this.config.temperature;
|
|
638
|
+
const model = context.meshProvider?.model ??
|
|
639
|
+
process.env.MESH_LLM_MODEL ??
|
|
640
|
+
this.config.model ??
|
|
641
|
+
this.getDefaultModel();
|
|
642
|
+
let outputSchema;
|
|
643
|
+
if (this.config.returnSchema) {
|
|
644
|
+
try {
|
|
645
|
+
const jsonSchema = zodToJsonSchema(this.config.returnSchema);
|
|
646
|
+
const schemaName = jsonSchema.title ?? "Response";
|
|
647
|
+
outputSchema = { schema: jsonSchema, name: schemaName };
|
|
648
|
+
}
|
|
649
|
+
catch {
|
|
650
|
+
// skip
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
const provider = new MeshDelegatedProvider(context.meshProvider.endpoint, context.meshProvider.functionName, this.config.parallelToolCalls ?? false);
|
|
654
|
+
yield* provider.streamComplete(model, messages, toolDefs.length > 0 ? toolDefs : undefined, { maxOutputTokens: maxTokens, temperature, topP: this.config.topP, stop: this.config.stop, outputSchema });
|
|
655
|
+
}
|
|
734
656
|
/**
|
|
735
657
|
* Create a callable LlmAgent interface.
|
|
736
658
|
*/
|
|
@@ -772,30 +694,44 @@ export class MeshLlmAgent {
|
|
|
772
694
|
Object.defineProperty(callable, "setSystemPrompt", {
|
|
773
695
|
value: (prompt) => agent.setSystemPrompt(prompt),
|
|
774
696
|
});
|
|
697
|
+
// Attach stream method — async iterable for token-by-token output.
|
|
698
|
+
// Mirrors the callable's option-merging semantics so users get the same
|
|
699
|
+
// "context merge vs replace" behavior as the buffered call.
|
|
700
|
+
Object.defineProperty(callable, "stream", {
|
|
701
|
+
value: (message, options) => {
|
|
702
|
+
const contextMode = options?.contextMode ?? "merge";
|
|
703
|
+
let mergedTemplateContext;
|
|
704
|
+
if (contextMode === "replace" && options?.context) {
|
|
705
|
+
mergedTemplateContext = options.context;
|
|
706
|
+
}
|
|
707
|
+
else if (options?.context) {
|
|
708
|
+
mergedTemplateContext = { ...context.templateContext, ...options.context };
|
|
709
|
+
}
|
|
710
|
+
else {
|
|
711
|
+
mergedTemplateContext = context.templateContext ?? {};
|
|
712
|
+
}
|
|
713
|
+
const mergedContext = {
|
|
714
|
+
...context,
|
|
715
|
+
options: options ? { ...context.options, ...options } : context.options,
|
|
716
|
+
templateContext: mergedTemplateContext,
|
|
717
|
+
};
|
|
718
|
+
return agent.stream(message, mergedContext);
|
|
719
|
+
},
|
|
720
|
+
});
|
|
775
721
|
return callable;
|
|
776
722
|
}
|
|
777
723
|
/**
|
|
778
724
|
* Resolve the LLM provider to use.
|
|
779
725
|
*
|
|
780
|
-
*
|
|
781
|
-
* - MESH_LLM_PROVIDER: Override provider (only for direct mode, not mesh delegation)
|
|
726
|
+
* Mesh delegation only — a resolved meshProvider is required.
|
|
782
727
|
*/
|
|
783
728
|
resolveProvider(context) {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
729
|
+
if (!context.meshProvider) {
|
|
730
|
+
throw new Error("MeshLlmAgent requires a mesh-delegated provider. " +
|
|
731
|
+
"Configure your agent with provider: { capability: 'llm', tags: ['+claude'] } " +
|
|
732
|
+
"and ensure a matching @mesh.llm_provider is registered in the mesh.");
|
|
787
733
|
}
|
|
788
|
-
|
|
789
|
-
// Check env var override first (only for string provider, not mesh delegation object)
|
|
790
|
-
let providerSpec;
|
|
791
|
-
if (typeof this.config.provider === "string") {
|
|
792
|
-
providerSpec =
|
|
793
|
-
process.env.MESH_LLM_PROVIDER || this.config.provider || "claude";
|
|
794
|
-
}
|
|
795
|
-
else {
|
|
796
|
-
providerSpec = "claude"; // fallback default for non-mesh object config
|
|
797
|
-
}
|
|
798
|
-
return new VercelDirectProvider(providerSpec);
|
|
734
|
+
return new MeshDelegatedProvider(context.meshProvider.endpoint, context.meshProvider.functionName, this.config.parallelToolCalls ?? false);
|
|
799
735
|
}
|
|
800
736
|
/**
|
|
801
737
|
* Get provider name for metadata.
|
|
@@ -804,29 +740,12 @@ export class MeshLlmAgent {
|
|
|
804
740
|
if (context.meshProvider) {
|
|
805
741
|
return `mesh:${context.meshProvider.endpoint}`;
|
|
806
742
|
}
|
|
807
|
-
if (typeof this.config.provider === "string") {
|
|
808
|
-
// Return env var override if set, otherwise config value
|
|
809
|
-
return process.env.MESH_LLM_PROVIDER || this.config.provider;
|
|
810
|
-
}
|
|
811
743
|
return `mesh:${this.config.provider.capability}`;
|
|
812
744
|
}
|
|
813
745
|
/**
|
|
814
|
-
* Get default model
|
|
746
|
+
* Get default model — mesh delegation defers model selection to the provider.
|
|
815
747
|
*/
|
|
816
748
|
getDefaultModel() {
|
|
817
|
-
const provider = this.config.provider;
|
|
818
|
-
if (typeof provider === "string") {
|
|
819
|
-
// Map common provider names to models
|
|
820
|
-
const defaultModels = {
|
|
821
|
-
claude: "anthropic/claude-sonnet-4-5",
|
|
822
|
-
openai: "gpt-4o",
|
|
823
|
-
anthropic: "anthropic/claude-sonnet-4-5",
|
|
824
|
-
gpt4: "gpt-4o",
|
|
825
|
-
gpt35: "gpt-3.5-turbo",
|
|
826
|
-
};
|
|
827
|
-
return defaultModels[provider.toLowerCase()] ?? provider;
|
|
828
|
-
}
|
|
829
|
-
// Mesh delegation - model will be determined by the provider
|
|
830
749
|
return "default";
|
|
831
750
|
}
|
|
832
751
|
/**
|