@routecraft/ai 0.5.0-canary.9 → 0.5.0

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/README.md CHANGED
@@ -5,13 +5,13 @@ AI adapters and MCP integration for Routecraft. Call LLMs, run agents, generate
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @routecraft/ai
9
- ```
10
-
11
- or
8
+ # Bun (recommended)
9
+ bun add @routecraft/ai
12
10
 
13
- ```bash
11
+ # npm / pnpm / yarn
12
+ npm install @routecraft/ai
14
13
  pnpm add @routecraft/ai
14
+ yarn add @routecraft/ai
15
15
  ```
16
16
 
17
17
  ## Quick Start
@@ -41,10 +41,10 @@ const ctx = new ContextBuilder()
41
41
  await ctx.start();
42
42
  ```
43
43
 
44
- Run it as an MCP server:
44
+ Run it as an MCP server (requires Bun on the host):
45
45
 
46
46
  ```bash
47
- npx @routecraft/cli run capabilities/fetch-webpage.ts
47
+ bunx @routecraft/cli run capabilities/fetch-webpage.ts
48
48
  ```
49
49
 
50
50
  ## Two Modes
@@ -75,8 +75,8 @@ const ctx = new ContextBuilder()
75
75
  )
76
76
  .enrich(http({ url: (ex) => ex.body.url }))
77
77
  .to(llm('anthropic:claude-sonnet-4-6', {
78
- systemPrompt: 'Summarize the following webpage content concisely.',
79
- userPrompt: (ex) => String(ex.body),
78
+ system: 'Summarize the following webpage content concisely.',
79
+ user: (ex) => String(ex.body),
80
80
  })),
81
81
  ])
82
82
  .build();
package/dist/index.cjs CHANGED
@@ -1,3 +1,15 @@
1
- 'use strict';var routecraft=require('@routecraft/routecraft'),ai=require('ai'),async_hooks=require('async_hooks'),http=require('http');var ie={McpAdapter:Symbol.for("routecraft.ai.McpAdapter")};function Ce(n,e){return typeof n=="object"&&n!==null&&n[e]===true}function xe(n){return Ce(n,ie.McpAdapter)}function D(n,e){throw new Error(`The ${e} LLM provider requires the "${n}" package. Install it with: pnpm add ${n}`)}function _(n,e){if(!(n instanceof Error))return false;let t=n.message??"";return (t.includes("ERR_MODULE_NOT_FOUND")||t.includes("Cannot find module")||t.includes("Cannot find package"))&&t.includes(e)}var Ae={ollama:{baseURL:"http://localhost:11434/api"}};function U(n){return {...n.inputTokens!==void 0&&{inputTokens:n.inputTokens},...n.outputTokens!==void 0&&{outputTokens:n.outputTokens},...n.totalTokens!==void 0&&{totalTokens:n.totalTokens}}}function j(n){try{if("output"in n&&n.output!==void 0)return n.output}catch{}}function se(n,e,t){if(n===null||typeof n!="object")throw new Error(`[${e}] Invalid model: expected an object, got ${typeof n}. Model id: ${t}`);let r=n;if(typeof r.doGenerate!="function")throw new Error(`[${e}] Invalid model: missing or invalid doGenerate method. Model id: ${t}. Ensure the provider returns an AI SDK-compatible language model.`);if(typeof r.doStream!="function")throw new Error(`[${e}] Invalid model: missing or invalid doStream method. Model id: ${t}. Ensure the provider returns an AI SDK-compatible language model.`)}async function ae(n){let{config:e,modelId:t,options:r,systemPrompt:o,userPrompt:i,output:s}=n;switch(e.provider){case "openai":return ke(e,t,r,o,i,s);case "anthropic":return Oe(e,t,r,o,i,s);case "gemini":return Le(e,t,r,o,i,s);case "openrouter":return Ie(e,t,r,o,i,s);case "ollama":return De(e,t,r,o,i,s);default:{let a=e;throw new Error(`LLM provider not implemented: ${a.provider}`)}}}async function ke(n,e,t,r,o,i){let s;try{s=(await import('@ai-sdk/openai')).createOpenAI;}catch(g){throw _(g,"@ai-sdk/openai")&&D("@ai-sdk/openai","OpenAI"),g}let{generateText:a}=await import('ai'),c={apiKey:n.apiKey};n.baseURL!==void 0&&(c.baseURL=n.baseURL);let d={model:s(c)(e),prompt:o,...t.maxTokens!==void 0&&{maxOutputTokens:t.maxTokens},temperature:t.temperature};r&&(d.system=r),t.topP!==void 0&&(d.topP=t.topP),t.frequencyPenalty!==void 0&&(d.frequencyPenalty=t.frequencyPenalty),t.presencePenalty!==void 0&&(d.presencePenalty=t.presencePenalty);let l=i!==void 0?{...d,output:i}:d,u=await a(l),m={text:u.text??"",raw:u};u.usage&&(m.usage=U(u.usage));let h=j(u);return h!==void 0&&(m.output=h),m}async function Oe(n,e,t,r,o,i){let s;try{s=(await import('@ai-sdk/anthropic')).createAnthropic;}catch(h){throw _(h,"@ai-sdk/anthropic")&&D("@ai-sdk/anthropic","Anthropic"),h}let{generateText:a}=await import('ai'),p={model:s({apiKey:n.apiKey})(e),prompt:o,...t.maxTokens!==void 0&&{maxOutputTokens:t.maxTokens},temperature:t.temperature};r&&(p.system=r),t.topP!==void 0&&(p.topP=t.topP),t.frequencyPenalty!==void 0&&(p.frequencyPenalty=t.frequencyPenalty),t.presencePenalty!==void 0&&(p.presencePenalty=t.presencePenalty);let d=i!==void 0?{...p,output:i}:p,l=await a(d),u={text:l.text??"",raw:l};l.usage&&(u.usage=U(l.usage));let m=j(l);return m!==void 0&&(u.output=m),u}async function Le(n,e,t,r,o,i){let s;try{s=(await import('@ai-sdk/google')).createGoogleGenerativeAI;}catch(h){throw _(h,"@ai-sdk/google")&&D("@ai-sdk/google","Gemini"),h}let{generateText:a}=await import('ai'),p={model:s({apiKey:n.apiKey})(e),prompt:o,...t.maxTokens!==void 0&&{maxOutputTokens:t.maxTokens},temperature:t.temperature};r&&(p.system=r),t.topP!==void 0&&(p.topP=t.topP),t.frequencyPenalty!==void 0&&(p.frequencyPenalty=t.frequencyPenalty),t.presencePenalty!==void 0&&(p.presencePenalty=t.presencePenalty);let d=i!==void 0?{...p,output:i}:p,l=await a(d),u={text:l.text??"",raw:l};l.usage&&(u.usage=U(l.usage));let m=j(l);return m!==void 0&&(u.output=m),u}async function Ie(n,e,t,r,o,i){let s;try{s=(await import('@openrouter/ai-sdk-provider')).createOpenRouter;}catch(y){throw _(y,"@openrouter/ai-sdk-provider")&&D("@openrouter/ai-sdk-provider","OpenRouter"),y}let{generateText:a}=await import('ai'),c=s({apiKey:n.apiKey}),f=n.modelId??e,p=c.chat(f);se(p,"OpenRouter",f);let l={model:p,prompt:o,...t.maxTokens!==void 0&&{maxOutputTokens:t.maxTokens},temperature:t.temperature};r&&(l.system=r),t.topP!==void 0&&(l.topP=t.topP),t.frequencyPenalty!==void 0&&(l.frequencyPenalty=t.frequencyPenalty),t.presencePenalty!==void 0&&(l.presencePenalty=t.presencePenalty);let u=i!==void 0?{...l,output:i}:l,m=await a(u),h={text:m.text??"",raw:m};m.usage&&(h.usage=U(m.usage));let g=j(m);return g!==void 0&&(h.output=g),h}async function De(n,e,t,r,o,i){let s;try{s=(await import('ollama-ai-provider-v2')).createOllama;}catch(y){throw _(y,"ollama-ai-provider-v2")&&D("ollama-ai-provider-v2","Ollama"),y}let{generateText:a}=await import('ai'),c=s({baseURL:n.baseURL??Ae.ollama.baseURL}),f=n.modelId??e,p=c(f);se(p,"Ollama",f);let l={model:p,prompt:o,...t.maxTokens!==void 0&&{maxOutputTokens:t.maxTokens},temperature:t.temperature};r&&(l.system=r),t.topP!==void 0&&(l.topP=t.topP),t.frequencyPenalty!==void 0&&(l.frequencyPenalty=t.frequencyPenalty),t.presencePenalty!==void 0&&(l.presencePenalty=t.presencePenalty);let u=i!==void 0?{...l,output:i}:l,m=await a(u),h={text:m.text??"",raw:m};m.usage&&(h.usage=U(m.usage));let g=j(m);return g!==void 0&&(h.output=g),h}function le(n){let e=n["~standard"];if(!e?.validate)throw new Error("LLM outputSchema must be a StandardSchemaV1 with ~standard.validate");let t=e.jsonSchema?.output?.({target:"draft-2020-12"})??e.jsonSchema?.input?.({target:"draft-2020-12"});if(!t||typeof t!="object")throw new Error("LLM outputSchema must expose ~standard.jsonSchema.output or .input for provider structured output");function r(i){let s;try{s=e.validate(i);}catch(c){return {success:false,error:c instanceof Error?c:new Error(String(c))}}return s instanceof Promise?{success:false,error:new Error("Async output schema is not supported for LLM structured output")}:s.issues!=null&&(Array.isArray(s.issues)?s.issues.length>0:typeof s.issues=="object"&&s.issues!==null?Object.keys(s.issues).length>0:!!s.issues)?{success:false,error:new Error(routecraft.formatSchemaIssues(s.issues))}:{success:true,value:s.value}}let o=ai.jsonSchema(t,{validate:r});return ai.Output.object({schema:o})}var S=Symbol.for("routecraft.adapter.llm.providers"),T=Symbol.for("routecraft.adapter.llm.options");async function He(n,e){let t;try{t=JSON.parse(n);}catch{return}let r=e["~standard"];if(!r?.validate)return;let o=r.validate(t);if(o instanceof Promise&&(o=await o),!(o&&typeof o=="object"&&"issues"in o&&o.issues))return o&&typeof o=="object"&&"value"in o?o.value:void 0}var qe=0,$e=1024;function pe(n,e){return n===void 0||n===""?"":typeof n=="function"?n(e):n}function Ve(n){let e=n.body;return typeof e=="string"?e:e==null?"":typeof e=="object"?JSON.stringify(e):String(e)}function ce(n){let e=n.indexOf(":");if(e<1||e===n.length-1)throw new Error(`LLM adapter: model id must be "providerId:modelName" (e.g. ollama:lfm2.5-thinking). Got: "${n}"`);return {providerId:n.slice(0,e),modelName:n.slice(e+1)}}function Ge(n,e){if(!e)throw new Error(`LLM adapter: model id "${n}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store "${S.description}" can be read.`);let t=e.getStore(S);if(!t)throw new Error('LLM provider not found: no providers registered. Add llmPlugin({ providers: { ollama: { provider: "ollama" }, ... } }) to your config.');let{providerId:r,modelName:o}=ce(n),i=t.get(r);if(!i)throw new Error(`LLM provider "${r}" not found. Register it with llmPlugin({ providers: { "${r}": { provider, apiKey?, baseURL? } } }).`);return {config:i,modelName:o}}var E=class{constructor(e,t={}){this.modelId=e;this.options=t;}modelId;adapterId="routecraft.adapter.llm";options;mergedOptions(e){let t=e.getStore(T);return {temperature:qe,maxTokens:$e,...t,...this.options}}async send(e){let t=routecraft.getExchangeContext(e),{config:r,modelName:o}=Ge(this.modelId,t),i=this.mergedOptions(t),s=pe(i.systemPrompt,e),a=pe(i.userPrompt,e)||Ve(e),c={temperature:i.temperature,maxTokens:i.maxTokens};i.topP!==void 0&&(c.topP=i.topP),i.frequencyPenalty!==void 0&&(c.frequencyPenalty=i.frequencyPenalty),i.presencePenalty!==void 0&&(c.presencePenalty=i.presencePenalty);let f=i.outputSchema!==void 0?le(i.outputSchema):void 0,p=await ae({config:r,modelId:o,options:c,systemPrompt:s,userPrompt:a,output:f});if(p.output===void 0&&p.text&&i.outputSchema!==void 0){let d=await He(p.text,i.outputSchema);d!==void 0&&(p.output=d);}return p}getMetadata(e){let t=e,{providerId:r}=ce(this.modelId),o={model:this.modelId,provider:r};return t.usage&&(t.usage.inputTokens!==void 0&&(o.inputTokens=t.usage.inputTokens),t.usage.outputTokens!==void 0&&(o.outputTokens=t.usage.outputTokens)),o}};function ue(n,e){return new E(n,e)}var de=["openai","anthropic","openrouter","ollama","gemini"];function Fe(n){return de.includes(n)}function q(n){if(!n||typeof n!="object")throw new TypeError("llmPlugin: options must be an object");if(!n.providers||typeof n.providers!="object")throw new TypeError("llmPlugin: options.providers must be an object (record of provider id \u2192 options)");for(let[e,t]of Object.entries(n.providers))if(t!==void 0){if(!t||typeof t!="object")throw new TypeError(`llmPlugin: providers["${e}"] must be an object`);if(!Fe(e))throw new TypeError(`llmPlugin: providers["${e}"] is not a supported provider. Supported: ${de.join(", ")}`);switch(e){case "openai":case "anthropic":case "openrouter":case "gemini":if(typeof t.apiKey!="string"||!t.apiKey.trim())throw new TypeError(`llmPlugin: providers["${e}"].apiKey is required`);break;case "ollama":if(t.baseURL!==void 0&&typeof t.baseURL!="string")throw new TypeError(`llmPlugin: providers["${e}"].baseURL must be a string when provided`);if(t.modelId!==void 0&&(typeof t.modelId!="string"||!t.modelId.trim()))throw new TypeError(`llmPlugin: providers["${e}"].modelId must be a non-empty string when provided`);break}}if(n.defaultOptions!==void 0&&(typeof n.defaultOptions!="object"||n.defaultOptions===null))throw new TypeError("llmPlugin: defaultOptions must be an object when provided")}var Be=["openai","anthropic","openrouter","ollama","gemini"];function Ke(n,e){return {provider:n,...e}}function me(n={providers:{}}){return q(n),{apply(e){let t=new Map;for(let r of Be){let o=n.providers[r];o!==void 0&&t.set(r,Ke(r,o));}e.setStore(S,t),n.defaultOptions&&Object.keys(n.defaultOptions).length>0&&e.setStore(T,n.defaultOptions);}}}var b=Symbol.for("routecraft.mcp.plugin.registered"),v=Symbol.for("routecraft.mcp.client.servers"),$=Symbol.for("routecraft.mcp.tool.registry"),C=Symbol.for("routecraft.mcp.stdio.managers"),V=(l=>(l.TOOL="routecraft.mcp.tool",l.SESSION="routecraft.mcp.session",l.AUTH_SUBJECT="routecraft.auth.subject",l.AUTH_SCHEME="routecraft.auth.scheme",l.AUTH_KIND="routecraft.auth.kind",l.AUTH_ROLES="routecraft.auth.roles",l.AUTH_SCOPES="routecraft.auth.scopes",l.AUTH_EMAIL="routecraft.auth.email",l.AUTH_NAME="routecraft.auth.name",l.AUTH_ISSUER="routecraft.auth.issuer",l.AUTH_AUDIENCE="routecraft.auth.audience",l.AUTH_CLIENT_ID="routecraft.auth.client_id",l))(V||{});function G(n){return "provider"in n&&n.provider==="oauth"}var R=Symbol.for("routecraft.mcp.adapter");var B=class{adapterId="routecraft.adapter.mcp";endpoint;options;constructor(e,t){if(this[R]=true,typeof e!="string")throw routecraft.rcError("RC5003",void 0,{message:"Dynamic endpoints cannot be used as source",suggestion:"Use a static string endpoint for source: .from(mcp('endpoint', options))."});if("url"in t||"serverId"in t)throw routecraft.rcError("RC5003",void 0,{message:"mcp() with url or serverId must be used as destination: .to(mcp({ url, tool }))",suggestion:"Use .to(mcp({ url: '...', tool: '...' })) to call a remote MCP server."});if("args"in t&&t.args!==void 0&&!("description"in t))throw routecraft.rcError("RC5003",void 0,{message:"mcp(endpoint, { args }) is for client usage with a 'server:tool' target, not for defining a source",suggestion:"Use .to(mcp('server:tool', { args })) to call a remote tool, or .from(mcp('endpoint', { description: '...' })) to define a source."});if(!("description"in t)||typeof t.description!="string")throw routecraft.rcError("RC5003",void 0,{message:"mcp(endpoint, options) as source requires options.description",suggestion:"Use .from(mcp('endpoint', { description: '...' })) to define a source."});this.endpoint=e,this.options=t;}async subscribe(e,t,r,o){if(e.getStore(b)!==true)throw new Error("MCP plugin required: routes using .from(mcp(...)) require the MCP plugin. Add mcpPlugin() to your config: plugins: [mcpPlugin()].");return routecraft.direct(this.endpoint,this.options).subscribe(e,t,r,o)}};function K(n){let e=n?.content;if(!Array.isArray(e)||e.length===0)return n;if(e.length===1){let t=e[0];if(t.type==="text"&&typeof t.text=="string")return t.text;if(typeof t.data=="string")return t.data}return e}var ge=new WeakMap;async function ze(n){if(typeof n=="function")return n();if(Array.isArray(n)){if(n.length===0)throw new Error("McpClientAuthOptions.token array must not be empty");let e=(ge.get(n)??0)%n.length;return ge.set(n,e+1),n[e]}return n}async function W(n){if(!n)return;let e={},t=n.headers??{},r=Object.entries(t).find(([o])=>o.toLowerCase()==="authorization")?.[1];if(r)e.Authorization=r;else if(n.token!==void 0){let o=await ze(n.token);if(o.length===0)throw new Error("McpClientAuthOptions.token must be a non-empty string when provided");e.Authorization=`Bearer ${o}`;}for(let[o,i]of Object.entries(t))o.toLowerCase()!=="authorization"&&(e[o]=i);return Object.keys(e).length>0?e:void 0}function Ye(n){let e=n.trim().toLowerCase();if(!e.startsWith("http://")&&!e.startsWith("https://"))throw new Error(`MCP client: url must be HTTP or HTTPS. Stdio is not supported in routes; register stdio clients via mcpPlugin({ clients: { name: { command, args } } }). Got: "${n.slice(0,50)}${n.length>50?"...":""}"`)}function Xe(n,e){return !n.serverId||!e?void 0:e.getStore(v)?.get(n.serverId)}function Qe(n,e){if(n.url)return Ye(n.url),{url:n.url,auth:n.auth};if(n.serverId&&!e)throw new Error(`MCP client: serverId "${n.serverId}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store "${String(v)}" can be read.`);if(n.serverId&&e){let t=Xe(n,e);if(!t)throw new Error(`MCP client: serverId "${n.serverId}" not found in context store. Register it with context store key "${String(v)}".`);let r=typeof t=="string"?t:t.url,o=n.auth??(typeof t=="object"&&"auth"in t?t.auth:void 0);return {url:r,auth:o}}throw new Error("MCP client: either url or serverId must be provided in McpClientOptions.")}var z=n=>typeof n.body=="object"&&n.body!==null?n.body:{input:n.body},N=class{constructor(e){this.options=e;if(this[R]=true,!e.url&&!e.serverId)throw new Error("MCP client: either url or serverId must be provided in McpClientOptions.");if(e.url&&e.serverId)throw new Error("MCP client: cannot provide both url and serverId. Use either url for direct HTTP or serverId for registered servers.")}options;adapterId="routecraft.adapter.mcp";async send(e){let t=routecraft.getExchangeContext(e),r=this.options.tool??(typeof e.body=="object"&&e.body!==null&&"tool"in e.body&&typeof e.body.tool=="string"?e.body.tool:void 0);if(!r)throw new Error("MCP client: tool name required. Set options.tool or exchange.body.tool.");let i=(this.options.args??z)(e);if(this.options.serverId&&t){let p=t.getStore(C)?.get(this.options.serverId);if(p){let u=await p.callTool(r,i);return u&&typeof u=="object"&&(u.metadata={toolName:r,transport:"stdio",serverId:this.options.serverId}),u}let l=t.getStore(v)?.get(this.options.serverId);if(l&&typeof l=="object"&&"transport"in l&&l.transport==="stdio")throw new Error(`MCP client: stdio server "${this.options.serverId}" is not running. Ensure mcpPlugin is applied and the stdio client started successfully.`)}let{url:s,auth:a}=Qe(this.options,t),c=await this.callRemoteTool(s,r,i,a);return c&&typeof c=="object"&&(c.metadata={toolName:r,url:s,transport:"http",...this.options.serverId?{serverId:this.options.serverId}:{}}),c}getMetadata(e){return e&&typeof e=="object"&&"metadata"in e?e.metadata:{toolName:"unknown",transport:"unknown"}}async callRemoteTool(e,t,r,o){let i,s;try{i=await import('@modelcontextprotocol/sdk/client/index.js'),s=await import('@modelcontextprotocol/sdk/client/streamableHttp.js');}catch{throw new Error('MCP client requires "@modelcontextprotocol/sdk". Install it with: pnpm add @modelcontextprotocol/sdk')}let a=i.Client,c=s.StreamableHTTPClientTransport,f=new URL(e),p=await W(o),d=p?{requestInit:{headers:p}}:void 0,l=new c(f,d),u={name:"routecraft-mcp-client",version:"1.0.0"},m=new a(u,{capabilities:{}});try{await m.connect.call(m,l);let y=await m.callTool.call(m,{name:t,arguments:r});return K(y)}finally{let h=m,g=h.close??h.disconnect;if(typeof g=="function")try{await Promise.resolve(g.call(m));}catch{}let y=l,P=y.close??y.destroy;if(typeof P=="function")try{await Promise.resolve(P.call(l));}catch{}}}};function H(n,e){if(typeof n=="object"&&n!==null&&("url"in n||"serverId"in n)){let o=n;if(typeof o.auth?.token=="string"&&o.auth.token.trim().length===0)throw new TypeError("mcp(): auth.token must be a non-empty string when provided");if(Array.isArray(o.auth?.token)){if(o.auth.token.length===0)throw new TypeError("mcp(): auth.token array must not be empty");for(let i=0;i<o.auth.token.length;i++){let s=o.auth.token[i];if(typeof s!="string"||s.trim().length===0)throw new TypeError(`mcp(): auth.token[${i}] must be a non-empty string`)}}return routecraft.tagAdapter(new N(o),H,routecraft.factoryArgs(n,e))}let t=e===void 0||typeof e=="object"&&e!==null&&!("description"in e);if(typeof n=="string"&&n.includes(":")&&t){let o=n.indexOf(":"),i=n.slice(0,o),s=n.slice(o+1),a={serverId:i,tool:s};return e!==void 0&&typeof e=="object"&&"args"in e&&e.args!==void 0&&(a.args=e.args),routecraft.tagAdapter(new N(a),H,routecraft.factoryArgs(n,e))}let r=n;if(e!==void 0)return routecraft.tagAdapter(new B(r,e),H,routecraft.factoryArgs(n,e));throw routecraft.rcError("RC5003",void 0,{message:"mcp() with only an endpoint is not supported. Use direct('endpoint') for in-process. For MCP server use .from(mcp('endpoint', { description: '...' })); for client use .to(mcp({ url, tool })) or .to(mcp('server:tool', { args })).",suggestion:"Use .from(mcp('endpoint', { description: '...' })) or .to(mcp({ url, tool })) or direct('endpoint')."})}function et(n){if(typeof n=="function")return async t=>n(t);let e=n;return async t=>t===e.client_id?e:void 0}function tt(n){if(!n)throw new TypeError("oauth: `verify` is required. Pass jwks(...), jwt(...), or a custom (token) => OAuthPrincipal function.");return typeof n=="function"?async e=>n(e):async e=>n.validator(e)}function fe(n){if(new URL(n.resourceIssuerUrl.toString()).protocol!=="https:"&&process.env.NODE_ENV==="production")throw new TypeError("oauth: resourceIssuerUrl must use HTTPS in production");let t=tt(n.verify),r=et(n.client);return {provider:"oauth",resourceIssuerUrl:n.resourceIssuerUrl,endpoints:n.endpoints,verifyAccessToken:t,getClient:r,...n.baseUrl!==void 0&&{baseUrl:n.baseUrl},...n.scopesSupported!==void 0&&{scopesSupported:n.scopesSupported},...n.requiredScopes!==void 0&&{requiredScopes:n.requiredScopes},...n.serviceDocumentationUrl!==void 0&&{serviceDocumentationUrl:n.serviceDocumentationUrl},...n.resourceName!==void 0&&{resourceName:n.resourceName}}}var ye=new async_hooks.AsyncLocalStorage,re='MCP server requires "@modelcontextprotocol/sdk". Install it with: pnpm add @modelcontextprotocol/sdk',A=class{context;options;server=null;transport=null;httpServer=null;httpSessions=new Map;running=false;toolsListLogged=false;constructor(e,t={}){this.context=e,this.options={name:"routecraft",version:"1.0.0",transport:"stdio",port:3001,host:"localhost",...t};}async start(){if(this.running){this.context.logger.warn({},"MCP server already running");return}try{let e=this.options.transport;e==="http"?await this.startHttp():await this.startStdio(),this.running=!0,this.context.logger.info({name:this.options.name,version:this.options.version,transport:e},"MCP server started"),this.logExposedToolsOnce();}catch(e){let t=routecraft.isRoutecraftError(e)?e.meta.message:e instanceof Error?e.message:"Failed to start MCP server";throw this.context.logger.error({err:e},t),e}}async startStdio(){let e,t;try{e=(await import('@modelcontextprotocol/sdk/server/index.js')).Server,t=(await import('@modelcontextprotocol/sdk/server/stdio.js')).StdioServerTransport;}catch{throw new Error(re)}this.server=new e({name:this.options.name,version:this.options.version},{capabilities:{tools:{}}}),await this.setupRequestHandlers(),this.transport=new t,await this.server.connect(this.transport);}async startHttp(){this.options.auth&&G(this.options.auth)?await this.startHttpWithOAuth(this.options.auth):await this.startHttpWithValidator();}async importSdkHttp(){let e;try{e=(await import('@modelcontextprotocol/sdk/server/index.js')).Server;}catch{throw new Error(re)}let r=(await import('@modelcontextprotocol/sdk/server/streamableHttp.js').catch(()=>null))?.StreamableHTTPServerTransport;if(!r)throw new Error("StreamableHTTPServerTransport not found in MCP SDK - ensure @modelcontextprotocol/sdk v1.26.0+ is installed");return {ServerCtor:e,TransportClass:r}}async createSession(e,t){let r=new e({name:this.options.name,version:this.options.version},{capabilities:{tools:{}}});await this.setupRequestHandlersOn(r);let o=new t({sessionIdGenerator:()=>crypto.randomUUID(),onsessioninitialized:f=>{this.httpSessions.set(f,{server:r,transport:o}),this.context.logger.debug({sessionId:f},"MCP session created"),this.context.emit("plugin:mcp:session:created",{sessionId:f});},enableJsonResponse:true});await r.connect(o);let s=o,a=s.onclose;s.onclose=()=>{let f=o.sessionId;f&&(this.httpSessions.delete(f),this.context.logger.debug({sessionId:f},"MCP session closed"),this.context.emit("plugin:mcp:session:closed",{sessionId:f})),a?.();};let c=o.handleRequest;if(typeof c!="function")throw new Error("StreamableHTTPServerTransport.handleRequest not found - SDK may have changed");return {transport:o,handleRequest:c.bind(o)}}async handleMcpRequest(e,t,r,o){let i=e.headers["mcp-session-id"],s=a=>ye.run(r,a);try{if(i&&this.httpSessions.has(i)){let a=this.httpSessions.get(i),c=a.transport.handleRequest;await s(()=>c.call(a.transport,e,t));}else if(!i||e.method==="POST"){let{handleRequest:a}=await o();await s(()=>a(e,t));}else t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Session not found"}));}catch(a){let c=routecraft.isRoutecraftError(a)?a.meta.message:a instanceof Error?a.message:"MCP HTTP request error";this.context.logger.error({err:a},c),t.headersSent||(t.writeHead(500,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Internal Server Error"})));}}async startHttpWithValidator(){let{ServerCtor:e,TransportClass:t}=await this.importSdkHttp(),r=this.options.port,o=this.options.host,i=()=>this.createSession(e,t);this.httpServer=http.createServer(async(s,a)=>{let c=s.url?.split("?")[0]??"";if(c!=="/mcp"&&c!=="/mcp/"){a.writeHead(404,{"Content-Type":"application/json"}),a.end(JSON.stringify({error:"Not Found",path:c}));return}let f;if(this.options.auth){let p=await this.validateAuth(s);if(!p){a.writeHead(401,{"Content-Type":"application/json","WWW-Authenticate":'Bearer realm="mcp"'}),a.end(JSON.stringify({error:"Unauthorized"}));return}f=p;}await this.handleMcpRequest(s,a,f,i);}),await this.listenHttp(r,o);}async startHttpWithOAuth(e){let{ServerCtor:t,TransportClass:r}=await this.importSdkHttp(),o,i,s,a;try{let g=await import('express');o=g.default??g;}catch{throw new Error('OAuth auth requires "express" (optional peer dependency of @routecraft/ai). Install it with: pnpm add express')}try{i=(await import('@modelcontextprotocol/sdk/server/auth/router.js')).mcpAuthRouter,s=(await import('@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js')).requireBearerAuth,a=(await import('@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js')).ProxyOAuthServerProvider;}catch{throw new Error("OAuth auth requires @modelcontextprotocol/sdk v1.27.0+ with OAuth support. Install it with: pnpm add @modelcontextprotocol/sdk")}let c=async g=>{let y;try{y=await e.verifyAccessToken(g);}catch(w){let M={reason:w instanceof Error?w.message:"invalid_token",scheme:"bearer",source:"mcp",path:"oauth"};throw this.context.logger.warn({err:w,...M},"Auth rejected: token validation failed"),this.context.emit("auth:rejected",M),w}if(y.expiresAt===void 0){let w={reason:"missing_expires_at",scheme:"bearer",source:"mcp",path:"oauth"};throw this.context.logger.warn(w,"Auth rejected: OAuth principal is missing expiresAt"),this.context.emit("auth:rejected",w),new Error("oauth: verifyAccessToken must return a principal with expiresAt (required by MCP SDK bearer middleware)")}return y.clientId||this.context.logger.debug({subject:y.subject},"oauth: principal missing clientId; using subject as fallback for AuthInfo.clientId"),{token:g,clientId:y.clientId??y.subject,scopes:y.scopes??[],expiresAt:y.expiresAt,extra:{principal:y}}},f=new a({endpoints:{authorizationUrl:e.endpoints.authorizationUrl,tokenUrl:e.endpoints.tokenUrl,revocationUrl:e.endpoints.revocationUrl,registrationUrl:e.endpoints.registrationUrl},verifyAccessToken:c,getClient:e.getClient}),p=this.options.port,d=this.options.host,l=o(),u={provider:f,issuerUrl:new URL(e.resourceIssuerUrl.toString())};e.baseUrl&&(u.baseUrl=new URL(e.baseUrl.toString())),e.scopesSupported&&(u.scopesSupported=e.scopesSupported),e.serviceDocumentationUrl&&(u.serviceDocumentationUrl=new URL(e.serviceDocumentationUrl.toString())),e.resourceName&&(u.resourceName=e.resourceName),l.use(i(u));let m={verifier:f};e.requiredScopes&&(m.requiredScopes=e.requiredScopes),l.use("/mcp",s(m));let h=()=>this.createSession(t,r);l.all("/mcp",async(g,y)=>{let P=g,w=y,I=g.auth,M=this.authInfoToPrincipal(I);if(M){let oe={subject:M.subject,scheme:M.scheme,source:"mcp"};this.context.logger.info(oe,"Auth succeeded"),this.context.emit("auth:success",oe);}await this.handleMcpRequest(P,w,M,h);}),this.httpServer=http.createServer(l),await this.listenHttp(p,d);}async listenHttp(e,t){await new Promise((i,s)=>{this.httpServer.listen(e,t,()=>i()),this.httpServer.on("error",a=>{let c=routecraft.isRoutecraftError(a)?a.meta.message:a instanceof Error?a.message:"MCP HTTP server listen failed";this.context.logger.error({err:a},c),s(a);});});let r=this.getHttpPort()??e,o={host:t,port:r,path:"/mcp"};this.context.logger.info(o,"MCP HTTP server listening"),this.context.emit("plugin:mcp:server:listening",o);}authInfoToPrincipal(e){if(!e)return;let t=e.extra?.principal;if(t)return t;let r={kind:"oauth",scheme:"bearer",subject:e.clientId,clientId:e.clientId,scopes:e.scopes};return e.expiresAt!==void 0&&(r.expiresAt=e.expiresAt),r}getHttpPort(){let e=this.httpServer?.address();if(e&&typeof e=="object"&&"port"in e)return e.port}async validateAuth(e){let t=this.options.auth;if(!t||!("validator"in t))return null;let r=e.headers.authorization;if(!r||Array.isArray(r)){let s={reason:"missing_header",scheme:"bearer",source:"mcp"};return this.context.logger.warn(s,"Auth rejected: missing or malformed Authorization header"),this.context.emit("auth:rejected",s),null}let o=/^bearer\s+(.+)$/i.exec(r);if(!o){let s={reason:"unsupported_scheme",scheme:"bearer",source:"mcp"};return this.context.logger.warn(s,"Auth rejected: unsupported authorization scheme"),this.context.emit("auth:rejected",s),null}let i=o[1];try{let s=await t.validator(i),a={subject:s.subject,scheme:s.scheme,source:"mcp"};return this.context.logger.info(a,"Auth succeeded"),this.context.emit("auth:success",a),s}catch(s){let c={reason:s instanceof Error?s.message:"invalid_token",scheme:"bearer",source:"mcp"};return this.context.logger.warn({err:s,...c},"Auth rejected: token validation failed"),this.context.emit("auth:rejected",c),null}}async setupRequestHandlers(){await this.setupRequestHandlersOn(this.server);}async setupRequestHandlersOn(e){let t;try{t=await import('@modelcontextprotocol/sdk/types.js');}catch{throw new Error(re)}let r=t,o=r.ListToolsRequestSchema,i=r.CallToolRequestSchema;if(!o||!i)throw new Error("MCP SDK types missing ListToolsRequestSchema or CallToolRequestSchema - ensure @modelcontextprotocol/sdk is installed");let s=e;s.setRequestHandler(o,async()=>{let a=this.getAvailableTools();return this.logExposedToolsOnce(),{tools:a}}),s.setRequestHandler(i,async a=>{let f=a.params;return await this.handleToolCall(f.name||"",f.arguments||{})});}async stop(){if(this.running)try{if(this.httpServer){for(let[,e]of this.httpSessions){let t=e.transport;typeof t.close=="function"&&await t.close();}this.httpSessions.clear(),await new Promise(e=>{this.httpServer.close(()=>e());}),this.httpServer=null;}if(this.transport){let e=this.transport;typeof e.close=="function"&&await e.close();}this.running=!1,this.context.logger.info({},"MCP server stopped");}catch(e){let t=routecraft.isRoutecraftError(e)?e.meta.message:e instanceof Error?e.message:"Error stopping MCP server";this.context.logger.error({err:e},t);}}logExposedToolsOnce(){if(this.toolsListLogged)return;let e=this.getAvailableTools();if(e.length===0)return;let t=e.map(o=>o.name),r={tools:t,count:t.length};this.context.logger.info(r,"Exposing MCP tools"),this.context.emit("plugin:mcp:server:tools:exposed",r),this.toolsListLogged=true;}getAvailableTools(){let e=this.context.getStore(routecraft.ADAPTER_DIRECT_REGISTRY);if(!e)return [];let t=Array.from(e.values()).filter(o=>o.description!==void 0),r=this.options.tools;if(r)if(Array.isArray(r)){let o=new Set(r);t=t.filter(i=>o.has(i.endpoint));}else typeof r=="function"&&(t=t.filter(r));return t.map(o=>this.metadataToMcpTool(o))}metadataToMcpTool(e){let t={name:e.endpoint,description:e.description||"",inputSchema:this.schemaToJsonSchema(e.schema)};return e.annotations!==void 0&&(t.annotations=e.annotations),t}schemaToJsonSchema(e){if(!e||typeof e!="object")return {type:"object"};let t=e["~standard"];if(t?.jsonSchema?.input)try{let r=t.jsonSchema.input({target:"draft-2020-12"});return typeof r=="object"&&r!==null?r:{type:"object"}}catch(r){return this.context.logger.debug(r,"Standard JSON Schema conversion failed"),{type:"object"}}return "~standard"in e?{type:"object",additionalProperties:true}:{type:"object"}}async handleToolCall(e,t){try{let r=this.context.getStore(routecraft.ADAPTER_DIRECT_STORE);if(!r){let l=new Error("No direct channels available");return this.context.emit("plugin:mcp:tool:failed",{tool:e,error:l.message}),{isError:!0,content:[{type:"text",text:"Error: No direct channels available"}]}}let o=r.get(e);if(!o){let l=new Error(`Tool not found: ${e}`);return this.context.emit("plugin:mcp:tool:failed",{tool:e,error:l.message}),{isError:!0,content:[{type:"text",text:`Error: Tool not found: ${e}`}]}}let i=typeof t=="string"?(()=>{try{return JSON.parse(t)||{}}catch{return {input:t}}})():t&&typeof t=="object"?t:{};this.context.logger.debug({bodyType:typeof i,body:i},"MCP tool call exchange body");let s=ye.getStore(),a={"routecraft.mcp.tool":e,"routecraft.mcp.session":`mcp-${Date.now()}`};s&&(a["routecraft.auth.subject"]=s.subject,a["routecraft.auth.scheme"]=s.scheme,a["routecraft.auth.kind"]=s.kind,s.name&&(a["routecraft.auth.name"]=s.name),s.email&&(a["routecraft.auth.email"]=s.email),s.roles&&(a["routecraft.auth.roles"]=s.roles),s.scopes&&(a["routecraft.auth.scopes"]=s.scopes),s.issuer&&(a["routecraft.auth.issuer"]=s.issuer),s.audience&&(a["routecraft.auth.audience"]=s.audience),s.clientId&&(a["routecraft.auth.client_id"]=s.clientId));let c=new routecraft.DefaultExchange(this.context,{body:i,headers:a});this.context.emit("plugin:mcp:tool:called",{tool:e,args:t});let p=await o.send(e,c),d=typeof p.body=="string"?p.body:JSON.stringify(p.body);return this.context.emit("plugin:mcp:tool:completed",{tool:e}),{content:[{type:"text",text:d}]}}catch(r){let o=routecraft.isRoutecraftError(r)?r.meta.message:r instanceof Error?r.message:String(r);this.context.logger.error({tool:e,err:r},o),this.context.emit("plugin:mcp:tool:failed",{tool:e,error:o});let i=o;if(routecraft.isRoutecraftError(r)){let s=r.cause;s?.message&&(i=`${o}: ${s.message}`);}return {content:[{type:"text",text:`Error: ${i}`}],isError:true}}}};function we(n){if(n.transport==="http"){if(n.port!==void 0){if(typeof n.port!="number")throw new TypeError("mcpPlugin: when transport is 'http', port must be a number");if(n.port<0||n.port>65535)throw new RangeError("mcpPlugin: port must be between 0 and 65535 when transport is 'http'")}if(n.host!==void 0&&typeof n.host!="string")throw new TypeError("mcpPlugin: when provided, host must be a string")}if(n.auth!==void 0)if("provider"in n.auth){if(n.auth.provider!=="oauth")throw new TypeError('mcpPlugin: auth.provider must be "oauth". Use the oauth() helper.')}else if("validator"in n.auth){if(typeof n.auth.validator!="function")throw new TypeError("mcpPlugin: auth.validator must be a function that returns a Principal (throw to reject)")}else throw new TypeError("mcpPlugin: auth must have either a 'validator' function or 'provider' set to 'oauth'. Use jwt(), jwks(), oauth(), or a custom { validator } object.");if(n.clients){for(let[e,t]of Object.entries(n.clients))if(typeof t=="object"&&t!==null&&"transport"in t&&t.transport==="stdio"&&(!t.command||typeof t.command!="string"))throw new TypeError(`mcpPlugin: stdio client "${e}" must have a non-empty command string`)}if(n.maxRestarts!==void 0&&(typeof n.maxRestarts!="number"||!Number.isInteger(n.maxRestarts)||n.maxRestarts<0))throw new TypeError("mcpPlugin: maxRestarts must be a non-negative integer");if(n.restartDelayMs!==void 0&&(typeof n.restartDelayMs!="number"||n.restartDelayMs<=0))throw new TypeError("mcpPlugin: restartDelayMs must be a positive number");if(n.restartBackoffMultiplier!==void 0&&(typeof n.restartBackoffMultiplier!="number"||n.restartBackoffMultiplier<1))throw new TypeError("mcpPlugin: restartBackoffMultiplier must be >= 1");if(n.toolRefreshIntervalMs!==void 0&&(typeof n.toolRefreshIntervalMs!="number"||!Number.isInteger(n.toolRefreshIntervalMs)||n.toolRefreshIntervalMs<0))throw new TypeError("mcpPlugin: toolRefreshIntervalMs must be a non-negative integer")}async function ve(n,e){let t=e["~standard"];if(!t?.validate)throw new Error("mcpPlugin: schema must be a StandardSchemaV1 with ~standard.validate");let r=t.validate(n);if(r instanceof Promise&&(r=await r),r.issues)throw new Error(`mcpPlugin options validation failed: ${routecraft.formatSchemaIssues(r.issues)}`);if(r.value===void 0)throw new Error("mcpPlugin options validation failed: no value returned");return r.value}var at='MCP stdio client requires "@modelcontextprotocol/sdk". Install it with: pnpm add @modelcontextprotocol/sdk',J=class{constructor(e,t,r,o){this.options=e;this.logger=t;this.onEvent=r;this.onToolsUpdated=o;}options;logger;onEvent;onToolsUpdated;client=null;transport=null;running=false;stopping=false;restartCount=0;restartTimer=null;stabilityTimer=null;tools=[];async start(){if(this.running)return;this.stopping=false,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null);let e,t;try{e=await import('@modelcontextprotocol/sdk/client/index.js'),t=await import('@modelcontextprotocol/sdk/client/stdio.js');}catch{throw new Error(at)}let{serverId:r,command:o,args:i,env:s,cwd:a}=this.options;this.transport=new t.StdioClientTransport({command:o,args:i??[],...s?{env:s}:{},...a?{cwd:a}:{},stderr:"pipe"});let c=this.transport;c.onerror=f=>{this.logger.error({err:f,serverId:r},"Stdio client transport error"),this.onEvent(`plugin:mcp:client:${r}:error`,{serverId:r,error:f});},c.onclose=()=>{this.stopping||(this.running=false,this.handleDisconnect());},c.stderr?.on&&c.stderr.on("data",f=>{this.logger.debug({serverId:r,stderr:String(f).trimEnd()},"Stdio client stderr output");}),this.client=new e.Client({name:"routecraft-mcp-client",version:"1.0.0"},{capabilities:{},listChanged:{tools:{onChanged:(f,p)=>{p&&Array.isArray(p.tools)?(this.tools=p.tools,this.onToolsUpdated(r,this.tools),this.onEvent(`plugin:mcp:client:${r}:tools:listed`,{serverId:r,toolCount:this.tools.length})):this.refreshTools();}}}}),await this.client.connect(this.transport),this.running=true,await this.refreshTools(),this.logger.info({serverId:r,toolCount:this.tools.length},"Stdio client started"),this.onEvent(`plugin:mcp:client:${r}:started`,{serverId:r,toolCount:this.tools.length});}async stop(){this.stopping=true,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null),this.stabilityTimer&&(clearTimeout(this.stabilityTimer),this.stabilityTimer=null);let{serverId:e}=this.options;if(this.client){try{await this.client.close();}catch{}this.client=null;}if(this.transport){let t=this.transport;if(typeof t.close=="function")try{await Promise.resolve(t.close());}catch{}this.transport=null;}this.running=false,this.logger.info({serverId:e},"Stdio client stopped"),this.onEvent(`plugin:mcp:client:${e}:stopped`,{serverId:e,reason:"graceful"});}async callTool(e,t){if(!this.running||!this.client)throw new Error(`Stdio client "${this.options.serverId}" is not running. Cannot call tool "${e}".`);let r=await this.client.callTool({name:e,arguments:t});return K(r)}getTools(){return [...this.tools]}isRunning(){return this.running}async refreshTools(){if(!this.client)return;let{serverId:e}=this.options;try{let t=await this.client.listTools();this.tools=t.tools??[],this.onToolsUpdated(e,this.tools),this.onEvent(`plugin:mcp:client:${e}:tools:listed`,{serverId:e,toolCount:this.tools.length});}catch(t){this.logger.warn({err:t,serverId:e},"Failed to list tools for stdio client");}}handleDisconnect(){let{serverId:e,maxRestarts:t,restartDelayMs:r,restartBackoffMultiplier:o}=this.options;if(this.tools.length>0&&(this.tools=[],this.onToolsUpdated(e,[])),this.logger.warn({serverId:e},"Stdio client disconnected unexpectedly"),this.onEvent(`plugin:mcp:client:${e}:stopped`,{serverId:e,reason:"unexpected"}),this.restartCount>=t){this.logger.error({serverId:e,restartCount:this.restartCount,maxRestarts:t},"Stdio client exceeded max restarts, giving up"),this.onEvent(`plugin:mcp:client:${e}:error`,{serverId:e,error:new Error(`Max restarts (${t}) exceeded for stdio client "${e}"`)});return}let i=r*Math.pow(o,this.restartCount);this.logger.info({serverId:e,restartCount:this.restartCount,delayMs:i},"Scheduling stdio client restart"),this.restartTimer=setTimeout(()=>{this.restartTimer=null,this.restart();},i);}async restart(){let{serverId:e}=this.options;this.restartCount++,this.client=null,this.transport=null;try{await this.start(),this.logger.info({serverId:e,restartCount:this.restartCount},"Stdio client restarted successfully"),this.onEvent(`plugin:mcp:client:${e}:restarted`,{serverId:e,restartCount:this.restartCount});let t=this.options.restartDelayMs*2;this.stabilityTimer=setTimeout(()=>{this.stabilityTimer=null,this.running&&(this.restartCount=0);},t);}catch(t){this.logger.error({err:t,serverId:e,restartCount:this.restartCount},"Stdio client restart failed"),this.onEvent(`plugin:mcp:client:${e}:error`,{serverId:e,error:t}),this.handleDisconnect();}}};var k=class{tools=new Map;setToolsForSource(e,t,r){let o=new Map;for(let i of r){let s={name:i.name,inputSchema:i.inputSchema,source:e,transport:t};i.description!==void 0&&(s.description=i.description),i.annotations!==void 0&&(s.annotations=i.annotations),o.set(i.name,s);}this.tools.set(e,o);}removeSource(e){this.tools.delete(e);}getTools(){let e=[];for(let t of this.tools.values())for(let r of t.values())e.push(r);return e}getToolsByServer(e){let t=this.tools.get(e);return t?Array.from(t.values()):[]}getTool(e){for(let t of this.tools.values()){let r=t.get(e);if(r)return r}}getToolBySource(e,t){return this.tools.get(e)?.get(t)}};function Pe(n){return "transport"in n&&n.transport==="stdio"}function Me(n={}){we(n);let e=null,t=new Map,r=new Map,o=[],i=null;return {async apply(p){if(p.setStore(b,true),i=new k,p.setStore($,i),p.setStore(C,t),n.clients&&Object.keys(n.clients).length>0){let d=Object.entries(n.clients),l=new Map;for(let[u,m]of d)l.set(u,m);p.setStore(v,l);for(let[u,m]of d){if(Pe(m))await s(p,u,m,i);else {let g=m;await c(p,u,g.url,i,g.auth),f(p,u,g.url,i,g.auth);}let h=Pe(m)?"stdio":"http";p.emit(`plugin:mcp:client:${u}:registered`,{serverId:u,transport:h});}}e=new A(p,n),await e.start();},async teardown(p){for(let d of o)clearInterval(d);o.length=0;for(let[d,l]of r)try{await l.close();}catch(u){p.logger.error({err:u,serverId:d,operation:"close"},"Failed to close HTTP client");}r.clear();for(let[d,l]of t)try{await l.stop();}catch(u){p.logger.error({err:u,serverId:d,operation:"stop"},"Failed to stop stdio client");}if(t.clear(),e){try{await e.stop();}catch(d){p.logger.error({err:d,operation:"stop"},"Failed to stop MCP server plugin");}e=null;}i=null;}};async function s(p,d,l,u){let m={serverId:d,command:l.command,args:l.args??[],maxRestarts:n.maxRestarts??5,restartDelayMs:n.restartDelayMs??1e3,restartBackoffMultiplier:n.restartBackoffMultiplier??2};l.env!==void 0&&(m.env=l.env),l.cwd!==void 0&&(m.cwd=l.cwd);let h=new J(m,p.logger,(g,y)=>{p.emit(g,y);},(g,y)=>{u.setToolsForSource(g,"stdio",y);});t.set(d,h);try{await h.start();}catch(g){p.logger.error({err:g,serverId:d,operation:"start"},"Failed to start stdio client"),p.emit(`plugin:mcp:client:${d}:error`,{serverId:d,error:g});}}async function a(p,d,l){let u=r.get(p);if(u)return u;let{Client:m}=await import('@modelcontextprotocol/sdk/client/index.js'),{StreamableHTTPClientTransport:h}=await import('@modelcontextprotocol/sdk/client/streamableHttp.js'),g=await W(l),y=g?{requestInit:{headers:g}}:void 0,P=new h(new URL(d),y),w=new m({name:"routecraft-mcp-client",version:"1.0.0"},{capabilities:{}});await w.connect(P);let I=w;return r.set(p,I),I}async function c(p,d,l,u,m){try{let y=(await(await a(d,l,m)).listTools()).tools??[];u.setToolsForSource(d,"http",y),p.emit(`plugin:mcp:client:${d}:tools:listed`,{serverId:d,toolCount:y.length});}catch(h){r.delete(d),p.logger.warn({err:h,serverId:d,url:l,operation:"listTools"},"Failed to list tools from HTTP client");}}function f(p,d,l,u,m){let h=n.toolRefreshIntervalMs??6e4;if(h<=0)return;let g=setInterval(()=>{c(p,d,l,u,m);},h);o.push(g);}}var Y=class{constructor(e){this._options=e;}_options;async run(e){return this._options,e.logger&&e.logger.debug({adapter:"agent"},"Agent pass-through \u2014 implementation pending"),{output:e.body,steps:0}}};function lt(n){let e=n.indexOf(":");if(e<1||e===n.length-1)throw new Error(`Agent adapter: modelId must be "providerId:modelName" (e.g. ollama:llama3). Got: "${n}"`)}var O=class{adapterId="routecraft.adapter.agent";runner;constructor(e){lt(e.modelId),this.runner=new Y(e);}async send(e){return this.runner.run(e)}};function Se(n){return new O(n)}var X=new Map;async function Q(){let n=[...X.entries()];X.clear(),n.length!==0&&await Promise.all(n.map(async([,e])=>{try{typeof e.dispose=="function"&&await e.dispose();}catch{}}));}function pt(n){return n.includes("/")?n:`Xenova/${n}`}var ct='The Hugging Face embedding provider requires "@huggingface/transformers". Install it with: pnpm add @huggingface/transformers';function ut(n,e){if(!(n instanceof Error))return false;let t=n.message??"";return (t.includes("ERR_MODULE_NOT_FOUND")||t.includes("Cannot find module")||t.includes("Cannot find package"))&&t.includes(e)}async function dt(n){let e=pt(n),t=X.get(e);if(t)return t.run;let r;try{r=(await import('@huggingface/transformers')).pipeline;}catch(a){throw ut(a,"@huggingface/transformers")?new Error(ct):a}let o=await r("feature-extraction",e,{dtype:"fp32"}),i=(a,c)=>o(a,{pooling:c?.pooling??"mean",normalize:c?.normalize??true}),s={run:i,dispose:typeof o.dispose=="function"?()=>Promise.resolve(o.dispose()):void 0};return X.set(e,s),i}function Re(n){if(n===null)return "null";if(typeof n!="object")return String(n);if(Array.isArray(n))return `array(${n.length})`;try{let e=JSON.stringify(n);return e.length>100?e.slice(0,100)+"...":e}catch{return "object"}}function mt(n){if(Array.isArray(n))return n;if(n instanceof Float32Array)return Array.from(n);if(n&&typeof n=="object"&&"data"in n){let e=n.data;if(Array.isArray(e))return e;if(e instanceof Float32Array)return Array.from(e);throw new Error(`Embedding output .data must be an Array or Float32Array; got ${typeof e}: ${Re(e)}`)}throw new Error(`Embedding output must be an Array, Float32Array, or object with .data; got ${typeof n}: ${Re(n)}`)}async function Te(n){let{config:e,modelName:t,text:r}=n;if(e.provider==="mock"){let i=[];for(let s=0;s<8;s++)i.push((r.length+s)%100/100);return i}if(e.provider==="huggingface"){let i=await(await dt(t))(r,{pooling:"mean",normalize:true}),s=i&&typeof i=="object"&&"data"in i?i.data:i;return mt(s)}throw e.provider==="ollama"||e.provider==="openai"?new Error(`Embedding provider "${e.provider}" is not yet implemented. Use huggingface for now.`):new Error(`Unknown embedding provider: ${e.provider}`)}var Z=Symbol.for("routecraft.adapter.embedding.providers"),ee=Symbol.for("routecraft.adapter.embedding.options");function ft(n){let e=n.indexOf(":");if(e<1||e===n.length-1)throw new Error(`Embedding adapter: model id must be "providerId:modelName" (e.g. huggingface:all-MiniLM-L6-v2). Got: "${n}"`);return {providerId:n.slice(0,e),modelName:n.slice(e+1)}}function ht(n,e){if(!e)throw new Error(`Embedding adapter: model id "${n}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so embedding providers can be read.`);let t=e.getStore(Z);if(!t)throw new Error("Embedding provider not found: no providers registered. Add embeddingPlugin({ providers: { huggingface: {} } }) to your config.");let{providerId:r,modelName:o}=ft(n),i=t.get(r);if(!i)throw new Error(`Embedding provider "${r}" not found. Register it with embeddingPlugin({ providers: { "${r}": {} } }).`);return {config:i,modelName:o}}function yt(n){return e=>{let t=n(e);return Array.isArray(t)?t.filter(Boolean).join(" | "):t}}var L=class{constructor(e,t={}){this.modelId=e;this.options=t;}modelId;adapterId="routecraft.adapter.embedding";options;mergedOptions(e){return {...e.getStore(ee),...this.options}}async send(e){let t=routecraft.getExchangeContext(e),{config:r,modelName:o}=ht(this.modelId,t),i=this.mergedOptions(t);if(!i.using)throw new Error("Embedding adapter: options.using(exchange) is required to build the string to embed.");let a=yt(i.using)(e);return {embedding:await Te({config:r,modelName:o,text:a})}}};function Ee(n,e){return new L(n,e)}function wt(n,e){return {...e,provider:n}}function be(n={providers:{}}){return {apply(e){let t=new Map;for(let[r,o]of Object.entries(n.providers))o!==void 0&&t.set(r,wt(r,o));e.setStore(Z,t),n.defaultOptions&&Object.keys(n.defaultOptions).length>0&&e.setStore(ee,n.defaultOptions);},async teardown(){await Q();}}}
2
- Object.defineProperty(exports,"jwks",{enumerable:true,get:function(){return routecraft.jwks}});Object.defineProperty(exports,"jwt",{enumerable:true,get:function(){return routecraft.jwt}});exports.ADAPTER_LLM_OPTIONS=T;exports.ADAPTER_LLM_PROVIDERS=S;exports.ADAPTER_MCP_CLIENT_SERVERS=v;exports.AgentDestinationAdapter=O;exports.BRAND=ie;exports.BRAND_MCP_ADAPTER=R;exports.EmbeddingDestinationAdapter=L;exports.LlmDestinationAdapter=E;exports.MCP_PLUGIN_REGISTERED=b;exports.MCP_STDIO_MANAGERS=C;exports.MCP_TOOL_REGISTRY=$;exports.McpHeadersKeys=V;exports.McpServer=A;exports.McpToolRegistry=k;exports.agent=Se;exports.defaultArgs=z;exports.disposeEmbeddingPipelineCache=Q;exports.embedding=Ee;exports.embeddingPlugin=be;exports.isMcpAdapter=xe;exports.isOAuthAuth=G;exports.llm=ue;exports.llmPlugin=me;exports.mcp=H;exports.mcpPlugin=Me;exports.oauth=fe;exports.validateLlmPluginOptions=q;exports.validateWithSchema=ve;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var routecraft=require('@routecraft/routecraft'),async_hooks=require('async_hooks'),http=require('http'),crypto$1=require('crypto'),ai=require('ai'),fs=require('fs'),path=require('path');var q=Symbol.for("routecraft.adapter.llm.providers"),ue=Symbol.for("routecraft.adapter.llm.options");var Ot=["openai","anthropic","openrouter","ollama","gemini"];function Nn(t){return Ot.includes(t)}function st(t){if(!t||typeof t!="object")throw new TypeError("llmPlugin: options must be an object");if(!t.providers||typeof t.providers!="object")throw new TypeError("llmPlugin: options.providers must be an object (record of provider id \u2192 options)");for(let[e,n]of Object.entries(t.providers))if(n!==void 0){if(!n||typeof n!="object")throw new TypeError(`llmPlugin: providers["${e}"] must be an object`);if(!Nn(e))throw new TypeError(`llmPlugin: providers["${e}"] is not a supported provider. Supported: ${Ot.join(", ")}`);switch(e){case "openai":case "anthropic":case "openrouter":case "gemini":if(typeof n.apiKey!="string"||!n.apiKey.trim())throw new TypeError(`llmPlugin: providers["${e}"].apiKey is required`);break;case "ollama":if(n.baseURL!==void 0&&typeof n.baseURL!="string")throw new TypeError(`llmPlugin: providers["${e}"].baseURL must be a string when provided`);if(n.modelId!==void 0&&(typeof n.modelId!="string"||!n.modelId.trim()))throw new TypeError(`llmPlugin: providers["${e}"].modelId must be a non-empty string when provided`);break}}if(t.defaultOptions!==void 0&&(typeof t.defaultOptions!="object"||t.defaultOptions===null))throw new TypeError("llmPlugin: defaultOptions must be an object when provided")}var $n=["openai","anthropic","openrouter","ollama","gemini"];function Un(t,e){return {provider:t,...e}}function ve(t={providers:{}}){return st(t),{apply(e){let n=new Map;for(let o of $n){let r=t.providers[o];r!==void 0&&n.set(o,Un(o,r));}e.setStore(q,n),t.defaultOptions&&Object.keys(t.defaultOptions).length>0&&e.setStore(ue,t.defaultOptions);}}}var pe=Symbol.for("routecraft.mcp.plugin.registered"),S=Symbol.for("routecraft.mcp.client.servers"),B=Symbol.for("routecraft.mcp.tool.registry"),me=Symbol.for("routecraft.mcp.stdio.managers"),O=Symbol.for("routecraft.mcp.local-tool-registry"),Ce=(n=>(n.TOOL="routecraft.mcp.tool",n.SESSION="routecraft.mcp.session",n))(Ce||{});function Pe(t){return "provider"in t&&t.provider==="oauth"}var jn="GET, POST, OPTIONS";var Fn="WWW-Authenticate, Mcp-Session-Id, Last-Event-ID",Hn=new Set(["localhost","127.0.0.1","::1","[::1]"]);function Gn(t){if(!t||t==="null")return false;let e;try{e=new URL(t);}catch{return false}return e.protocol!=="http:"&&e.protocol!=="https:"||e.username||e.password||e.pathname!=="/"&&e.pathname!==""||e.search||e.hash?false:Hn.has(e.hostname)?t:false}function at(t){if(t===false)return null;if(t===void 0)return {resolveOrigin:Gn,isWildcard:false};let{origin:e}=t;if(e==="*")return {resolveOrigin:()=>"*",isWildcard:true};if(typeof e=="string"){let n=e;return {resolveOrigin:o=>o===n?n:false,isWildcard:false}}if(Array.isArray(e)){let n=new Set(e);return {resolveOrigin:o=>o!==void 0&&n.has(o)?o:false,isWildcard:false}}if(typeof e=="function")return {resolveOrigin:e,isWildcard:false};throw new TypeError("mcpPlugin: cors.origin must be '*', a string, a string array, or a function")}function Vn(t,e){try{return t.resolveOrigin(e)}catch{return false}}function qn(t,e,n){if(!t)return {};let o={};t.isWildcard||(o.Vary="Origin");let r=Vn(t,e);return r===false||(o["Access-Control-Allow-Origin"]=r,n?(o["Access-Control-Allow-Methods"]=jn,o["Access-Control-Allow-Headers"]="*",o["Access-Control-Allow-Private-Network"]="true"):o["Access-Control-Expose-Headers"]=Fn),o}function fe(t,e,n,o){if(!e)return;let{Vary:r,...i}=qn(e,n,o);for(let[a,s]of Object.entries(i))t.setHeader(a,s);r!==void 0&&t.appendHeader("Vary",r);}var ke="/.well-known/oauth-protected-resource";function lt(t){let e=new Set([ke]),n=t.pathname;return n&&n!=="/"&&n!==""&&e.add(`${ke}${n}`),{ownedPaths:new Set([...e,"/mcp","/mcp/"]),metadataPaths:e}}var bt=t=>`<svg width="162" height="153" viewBox="0 0 162 153" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M141.881 62.9617C141.881 44.2319 126.65 29.0002 107.92 29.0002H30.1636L52.4304 52.2797L71.8879 52.3014L62.5672 42.4107H107.92C119.252 42.4107 128.471 51.6298 128.471 62.9617C128.471 74.293 119.252 83.5128 107.92 83.5128H101.193H88.5983H54.5814C50.8822 83.5128 47.8762 86.5187 47.8762 90.2173C47.8762 93.9278 50.8822 96.9225 54.5814 96.9225H95.4038L120.815 123.997H139.227L113.374 96.4753C129.522 93.8717 141.881 79.8359 141.881 62.9617Z" fill="${t}"/><path d="M54.8718 110.59C43.5966 110.59 34.4105 101.403 34.4105 90.1282C34.4105 78.8411 43.5966 69.6662 54.8718 69.6662H107.115C110.814 69.6662 113.82 66.6714 113.82 62.9617C113.82 59.2624 110.814 56.2564 107.115 56.2564H54.8718C36.1988 56.2564 21 71.4545 21 90.1282C21 108.802 36.1988 124 54.8718 124H113.597L101.014 110.59H54.8718Z" fill="${t}"/></svg>`,Et=t=>`data:image/svg+xml;base64,${Buffer.from(t,"utf8").toString("base64")}`,xt=Object.freeze([Object.freeze({src:Et(bt("#ffffff")),mimeType:"image/svg+xml",theme:"dark"}),Object.freeze({src:Et(bt("#000000")),mimeType:"image/svg+xml",theme:"light"})]);var Wn=["subject","issuer","audience","expiresAt","claims"],Kn=1e4,zn=3600,dt=class{entries=new Map;inFlight=new Map;maxEntries;constructor(e=Kn){this.maxEntries=e;}async getOrCompute(e,n,o){if(n===void 0||!Number.isFinite(n))return o();let r=Yn(e),i=this.entries.get(r);if(i){if(Date.now()/1e3<i.expiresAt)return i.enrichment;this.entries.delete(r);}let a=this.inFlight.get(r);if(a)return a;let s=o().then(l=>(this.store(r,l,n),this.inFlight.delete(r),l),l=>{throw this.inFlight.delete(r),l});return this.inFlight.set(r,s),s}clear(){this.entries.clear(),this.inFlight.clear();}store(e,n,o){for(this.entries.has(e)&&this.entries.delete(e),this.entries.set(e,{enrichment:n,expiresAt:o});this.entries.size>this.maxEntries;){let r=this.entries.keys().next().value;if(r===void 0)break;this.entries.delete(r);}}};function Yn(t){return crypto$1.createHash("sha256").update(t).digest("hex")}function Jn(t){if(!t)return;let e=t.match(/(?:^|,\s*)max-age=(\d+)/i);if(!e)return;let n=Number.parseInt(e[1],10);return Number.isFinite(n)&&n>=0?n:void 0}function Xn(t,e){if(t!==true){let l=new URL(t.toString());return async()=>l}if(e===void 0)throw new TypeError('oauth: `userinfo: true` requires the verify helper to expose an `issuer`. Use `jwks({ issuer, ... })` / `jwt({ issuer, ... })`, pass an explicit `userinfo: "https://idp.example.com/oauth/userinfo"`, or use a function.');if(Array.isArray(e))throw new TypeError("oauth: `userinfo: true` requires a single-string `issuer`; got an array. OIDC Discovery resolves one issuer to one userinfo endpoint. Pass an explicit userinfo URL or function instead.");let n=e.endsWith("/")?e:`${e}/`,o=new URL(".well-known/openid-configuration",n),r=null,i=0,a=null,s=async()=>{let l;try{l=await fetch(o);}catch(u){throw routecraft.rcError("RC5021",u,{message:`OIDC Discovery fetch failed at ${o.toString()}`,suggestion:"Verify network access to the IdP and that the issuer URL is reachable. Pass an explicit `userinfo` URL or function if the IdP does not advertise discovery."})}if(!l.ok)throw routecraft.rcError("RC5021",new Error(`OIDC Discovery fetch returned ${l.status} ${l.statusText}`),{message:`OIDC Discovery fetch failed at ${o.toString()} (status ${l.status})`,suggestion:"Verify the issuer hosts an OIDC Discovery document. Pass an explicit `userinfo` URL or function if it does not."});let d;try{d=await l.json();}catch(u){throw routecraft.rcError("RC5021",u,{message:`OIDC Discovery document at ${o.toString()} is not valid JSON`,suggestion:"Inspect the discovery endpoint manually. Pass an explicit `userinfo` URL or function if the IdP is non-compliant."})}if(typeof d.userinfo_endpoint!="string"||!d.userinfo_endpoint)throw routecraft.rcError("RC5021",new Error("missing userinfo_endpoint in discovery document"),{message:`OIDC Discovery document at ${o.toString()} does not advertise a userinfo_endpoint`,suggestion:"Pass an explicit `userinfo` URL or function for this IdP; it does not advertise auto-discoverable userinfo."});let c=new URL(d.userinfo_endpoint),m=Jn(l.headers.get("cache-control"))??zn;return r=c,i=Date.now()/1e3+m,c};return async()=>r&&Date.now()/1e3<i?r:a||(a=s().finally(()=>{a=null;}),a)}async function Zn(t,e){let n;try{n=await fetch(t,{headers:{Authorization:`Bearer ${e}`}});}catch(o){throw routecraft.rcError("RC5021",o,{message:`userinfo fetch failed at ${t.toString()}`,suggestion:"Verify network access to the IdP's userinfo endpoint and that the bearer token's scopes permit it."})}if(!n.ok)throw routecraft.rcError("RC5021",new Error(`userinfo returned ${n.status} ${n.statusText}`),{message:`userinfo fetch failed at ${t.toString()} (status ${n.status})`,suggestion:"Check the bearer token has the scopes required by the IdP's userinfo endpoint (typically `openid`, `email`, `profile`)."});try{return await n.json()}catch(o){throw routecraft.rcError("RC5021",o,{message:`userinfo response at ${t.toString()} is not valid JSON`,suggestion:"Inspect the userinfo endpoint manually; it must return a JSON object per OIDC Core \xA75.3.2."})}}function Lt(t,e){let n={...t};for(let[o,r]of Object.entries(e))Wn.includes(o)||r!==void 0&&(n[o]=r);return n}function Qn(t){let e={userinfoClaims:t};return typeof t.email=="string"&&(e.email=t.email),typeof t.name=="string"&&(e.name=t.name),Array.isArray(t.roles)&&(e.roles=t.roles.filter(n=>typeof n=="string")),e}function ct(t,e,n){let o=new dt;if(typeof e=="function")return async i=>{let a=await t(i),s=await o.getOrCompute(i,a.expiresAt,()=>e(a,i));return Lt(a,s)};let r=Xn(e,n);return async i=>{let a=await t(i),s=await o.getOrCompute(i,a.expiresAt,async()=>{let l=await r(),d=await Zn(l,i),c=d.sub;if(typeof c!="string"||c.length===0)throw routecraft.rcError("RC5022",new Error("userinfo response is missing `sub`"),{message:"userinfo response is missing `sub` (required per OIDC Core \xA75.3.2)",suggestion:"Inspect the userinfo endpoint manually; the response MUST include a `sub` claim. If the IdP returns a non-standard identifier, use a function-mode `userinfo` and map it yourself."});if(c!==a.subject)throw routecraft.rcError("RC5022",new Error(`userinfo \`sub\` (${c}) does not match token \`sub\` (${a.subject})`),{message:"userinfo response `sub` does not match the verified token's `sub` (OIDC Core \xA75.3.2 violation)",suggestion:"This indicates a compromised userinfo endpoint or a misconfigured userinfo URL. Verify the issuer / userinfo mapping; do not relax this check."});return Qn(d)});return Lt(a,s)}}function ut(t){return typeof t=="object"&&t!==null&&t.code==="ERR_JWT_EXPIRED"}var eo=new Set(["ERR_JWKS_TIMEOUT","ERR_JWKS_INVALID","ERR_JOSE_GENERIC"]),to=new Set(["ECONNREFUSED","ECONNRESET","ENOTFOUND","EAI_AGAIN","ETIMEDOUT","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT","UND_ERR_SOCKET"]);function It(t){let e=t;for(let n=0;n<5;n++){if(typeof e!="object"||e===null)return false;let o=e.code;if(typeof o=="string"&&(eo.has(o)||to.has(o)))return true;e=e.cause;}return false}var _t=new async_hooks.AsyncLocalStorage,W=class{context;options;server=null;transport=null;httpServer=null;httpSessions=new Map;running=false;toolsListLogged=false;validatorVerifier=null;constructor(e,n={}){this.context=e,this.options={name:"routecraft",version:"1.0.0",transport:"stdio",port:3001,host:"localhost",...n},this.validateResourceConfig();}resolveServerIcons(){return this.options.icons===void 0?xt:this.options.icons}defaultUnlessEmpty(e,n){let o=e??n;return o===""?void 0:o}buildServerInfo(){let e={name:this.options.name,version:this.options.version};this.options.title!==void 0&&(e.title=this.options.title);let n=this.defaultUnlessEmpty(this.options.description,"Powered by Routecraft.dev");n!==void 0&&(e.description=n);let o=this.defaultUnlessEmpty(this.options.websiteUrl,"https://routecraft.dev");o!==void 0&&(e.websiteUrl=o);let r=this.resolveServerIcons();return r.length>0&&(e.icons=r),e}buildServerOptions(){let e={capabilities:{tools:{}}},n=this.defaultUnlessEmpty(this.options.instructions,"");return n!==void 0&&(e.instructions=n),e}validateResourceConfig(){let e=this.options.resource?.url;if(e===void 0)return;if(new URL(e.toString()).protocol!=="https:"&&process.env.NODE_ENV==="production")throw new TypeError("mcpPlugin: resource.url must use HTTPS in production")}async start(){if(this.running){this.context.logger.warn({},"MCP server already running");return}try{let e=this.options.transport;e==="http"?await this.startHttp():await this.startStdio(),this.running=!0,this.context.logger.info({name:this.options.name,version:this.options.version,transport:e},"MCP server started"),this.logExposedToolsOnce();}catch(e){let n=routecraft.isRoutecraftError(e)?e.meta.message:e instanceof Error?e.message:"Failed to start MCP server";throw this.context.logger.error({err:e},n),e}}async startStdio(){let n=(await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/server/index.js'),{adapterName:"mcp (stdio)",packageName:"@modelcontextprotocol/sdk"})).Server,r=(await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/server/stdio.js'),{adapterName:"mcp (stdio)",packageName:"@modelcontextprotocol/sdk"})).StdioServerTransport;this.server=new n(this.buildServerInfo(),this.buildServerOptions()),await this.setupRequestHandlers(),this.transport=new r,await this.server.connect(this.transport);}async startHttp(){this.options.auth&&Pe(this.options.auth)?await this.startHttpWithOAuth(this.options.auth):await this.startHttpWithValidator();}async importSdkHttp(){let n=(await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/server/index.js'),{adapterName:"mcp (http)",packageName:"@modelcontextprotocol/sdk"})).Server,r=(await import('@modelcontextprotocol/sdk/server/streamableHttp.js').catch(()=>null))?.StreamableHTTPServerTransport;if(!r)throw new Error("StreamableHTTPServerTransport not found in MCP SDK - ensure @modelcontextprotocol/sdk v1.26.0+ is installed");return {ServerCtor:n,TransportClass:r}}async createSession(e,n){let o=new e(this.buildServerInfo(),this.buildServerOptions());await this.setupRequestHandlersOn(o);let r=new n({sessionIdGenerator:()=>crypto.randomUUID(),onsessioninitialized:d=>{this.httpSessions.set(d,{server:o,transport:r}),this.context.logger.debug({sessionId:d},"MCP session created"),this.context.emit("plugin:mcp:session:created",{sessionId:d});},enableJsonResponse:true});await o.connect(r);let a=r,s=a.onclose;a.onclose=()=>{let d=r.sessionId;d&&(this.httpSessions.delete(d),this.context.logger.debug({sessionId:d},"MCP session closed"),this.context.emit("plugin:mcp:session:closed",{sessionId:d})),s?.();};let l=r.handleRequest;if(typeof l!="function")throw new Error("StreamableHTTPServerTransport.handleRequest not found - SDK may have changed");return {transport:r,handleRequest:l.bind(r)}}async handleMcpRequest(e,n,o,r){let i=e.headers["mcp-session-id"],a=s=>_t.run(o,s);try{if(i&&this.httpSessions.has(i)){let s=this.httpSessions.get(i),l=s.transport.handleRequest;await a(()=>l.call(s.transport,e,n));}else if(!i||e.method==="POST"){let{handleRequest:s}=await r();await a(()=>s(e,n));}else n.writeHead(404,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:"Session not found"}));}catch(s){let l=routecraft.isRoutecraftError(s)?s.meta.message:s instanceof Error?s.message:"MCP HTTP request error";this.context.logger.error({err:s},l),n.headersSent||(n.writeHead(500,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:"Internal Server Error"})));}}resolveResourceUrl(){let e=this.options.resource?.url;if(e!==void 0)return e.toString();let n=this.options.host,o=this.getHttpPort()??this.options.port;return `http://${n}:${o}/mcp`}resolveResourceName(){return this.options.title??this.options.name}buildProtectedResourceMetadata(){let e={resource:this.resolveResourceUrl(),bearer_methods_supported:["header"]};e.resource_name=this.resolveResourceName();let n=this.options.auth;if(n&&!("provider"in n)&&"issuer"in n){let r=n.issuer;r!==void 0&&(e.authorization_servers=Array.isArray(r)?r:[r]);}let o=this.options.resource;return o?.scopesSupported&&o.scopesSupported.length>0&&(e.scopes_supported=o.scopesSupported),o?.documentationUrl!==void 0&&(e.resource_documentation=o.documentationUrl.toString()),e}resolveResourceMetadataUrl(){return new URL(ke,this.resolveResourceUrl()).toString()}buildWwwAuthenticateHeader(){return `Bearer realm="mcp", resource_metadata="${this.resolveResourceMetadataUrl()}"`}serveProtectedResourceMetadata(e){let n=this.buildProtectedResourceMetadata();e.writeHead(200,{"Content-Type":"application/json","Cache-Control":"public, max-age=3600"}),e.end(JSON.stringify(n));}async startHttpWithValidator(){let{ServerCtor:e,TransportClass:n}=await this.importSdkHttp(),o=this.options.port,r=this.options.host,i=at(this.options.cors);this.validatorVerifier=this.buildValidatorVerifier();let a=()=>this.createSession(e,n);this.httpServer=http.createServer(async(s,l)=>{let d=s.url?.split("?")[0]??"",c=s.headers.origin,m=Array.isArray(c)?c[0]:c,u=new URL(this.resolveResourceUrl()),{ownedPaths:p,metadataPaths:f}=lt(u);if(s.method==="OPTIONS"&&i!==null&&p.has(d)){fe(l,i,m,true),l.writeHead(204),l.end();return}if(s.method!=="OPTIONS"&&fe(l,i,m,false),f.has(d)){this.serveProtectedResourceMetadata(l);return}if(d!=="/mcp"&&d!=="/mcp/"){l.writeHead(404,{"Content-Type":"application/json"}),l.end(JSON.stringify({error:"Not Found",path:d}));return}let h;if(this.options.auth){let g=await this.validateAuth(s);if(!g){l.writeHead(401,{"Content-Type":"application/json","WWW-Authenticate":this.buildWwwAuthenticateHeader()}),l.end(JSON.stringify({error:"Unauthorized"}));return}h=g;}await this.handleMcpRequest(s,l,h,a);}),await this.listenHttp(o,r);}async startHttpWithOAuth(e){let{ServerCtor:n,TransportClass:o}=await this.importSdkHttp(),r;try{let P=await import('express');r=P.default??P;}catch{throw new Error('OAuth auth requires "express" (optional peer dependency of @routecraft/ai). Install it with: bun add express')}let a=(await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/server/auth/router.js'),{adapterName:"mcp (oauth)",packageName:"@modelcontextprotocol/sdk"})).mcpAuthRouter,l=(await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js'),{adapterName:"mcp (oauth)",packageName:"@modelcontextprotocol/sdk"})).requireBearerAuth,c=(await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js'),{adapterName:"mcp (oauth)",packageName:"@modelcontextprotocol/sdk"})).ProxyOAuthServerProvider,u=(await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/server/auth/errors.js'),{adapterName:"mcp (oauth)",packageName:"@modelcontextprotocol/sdk"})).InvalidTokenError,p=this.options.userinfo===void 0?e.verifyAccessToken:ct(e.verifyAccessToken,this.options.userinfo,e.issuer),f=async P=>{let C;try{C=await p(P);}catch(v){let A=ut(v),T={reason:v instanceof Error?v.message:"invalid_token",scheme:"bearer",source:"mcp",path:"oauth"};throw A?this.context.logger.debug({err:v,...T},"Auth rejected: token expired"):this.context.logger.warn({err:v,...T},"Auth rejected: token validation failed"),this.context.emit("auth:rejected",T),routecraft.isRoutecraftError(v)||It(v)?v:new u(A?"Token has expired":"Invalid token")}if(C.expiresAt===void 0){let v={reason:"missing_expires_at",scheme:"bearer",source:"mcp",path:"oauth"};throw this.context.logger.warn(v,"Auth rejected: OAuth principal is missing expiresAt"),this.context.emit("auth:rejected",v),new Error("oauth: verifyAccessToken must return a principal with expiresAt (required by MCP SDK bearer middleware)")}return C.clientId||this.context.logger.debug({subject:C.subject},"oauth: principal missing clientId; using subject as fallback for AuthInfo.clientId"),{token:P,clientId:C.clientId??C.subject,scopes:C.scopes??[],expiresAt:C.expiresAt,extra:{principal:C}}},h=new c({endpoints:{authorizationUrl:e.endpoints.authorizationUrl,tokenUrl:e.endpoints.tokenUrl,revocationUrl:e.endpoints.revocationUrl,registrationUrl:e.endpoints.registrationUrl},verifyAccessToken:f,getClient:e.getClient}),g=this.options.port,R=this.options.host;if(g===0&&this.options.resource?.url===void 0)throw new TypeError('mcpPlugin: OAuth-proxy mode requires either a fixed `port` or an explicit `resource.url`. With `port: 0` (ephemeral) and no `resource.url`, the protected-resource metadata URL would advertise `:0`. Pass `resource: { url: "https://..." }` or a non-zero `port`.');let x=new URL(this.resolveResourceUrl()),{ownedPaths:D,metadataPaths:G}=lt(x),V=r(),it=at(this.options.cors);it!==null&&V.use((P,C,Re)=>{let v=P,A=C,_=v.url?.split("?")[0]??"",T=v.headers.origin,At=Array.isArray(T)?T[0]:T;if(v.method==="OPTIONS"&&D.has(_)){fe(A,it,At,true),A.writeHead(204),A.end();return}v.method!=="OPTIONS"&&fe(A,it,At,false),Re();});let Dn=(P,C)=>{this.serveProtectedResourceMetadata(C);};for(let P of G)V.get(P,Dn);let de={provider:h,issuerUrl:x};e.baseUrl&&(de.baseUrl=new URL(e.baseUrl.toString()));let ce=this.options.resource;ce?.scopesSupported&&ce.scopesSupported.length>0&&(de.scopesSupported=ce.scopesSupported),ce?.documentationUrl!==void 0&&(de.serviceDocumentationUrl=new URL(ce.documentationUrl.toString()));let St=this.resolveResourceName();St&&(de.resourceName=St),V.use(a(de));let Mt={verifier:h,resourceMetadataUrl:this.resolveResourceMetadataUrl()};e.requiredScopes&&(Mt.requiredScopes=e.requiredScopes),V.use("/mcp",l(Mt));let _n=()=>this.createSession(n,o);V.all("/mcp",async(P,C)=>{let Re=P,v=C,A=P.auth,_=this.authInfoToPrincipal(A);if(_){let T={subject:_.subject,scheme:_.scheme,source:"mcp"};this.context.logger.info(T,"Auth succeeded"),this.context.emit("auth:success",T);}await this.handleMcpRequest(Re,v,_,_n);}),this.httpServer=http.createServer(V),await this.listenHttp(g,R);}async listenHttp(e,n){await new Promise((i,a)=>{this.httpServer.listen(e,n,()=>i()),this.httpServer.on("error",s=>{let l=routecraft.isRoutecraftError(s)?s.meta.message:s instanceof Error?s.message:"MCP HTTP server listen failed";this.context.logger.error({err:s},l),a(s);});});let o=this.getHttpPort()??e,r={host:n,port:o,path:"/mcp"};this.context.logger.info(r,"MCP HTTP server listening"),this.context.emit("plugin:mcp:server:listening",r);}authInfoToPrincipal(e){if(!e)return;let n=e.extra?.principal;if(n)return n;let o={kind:"oauth",scheme:"bearer",subject:e.clientId,clientId:e.clientId,scopes:e.scopes};return e.expiresAt!==void 0&&(o.expiresAt=e.expiresAt),o}getHttpPort(){let e=this.httpServer?.address();if(e&&typeof e=="object"&&"port"in e)return e.port}buildValidatorVerifier(){let e=this.options.auth;if(!e||!("validator"in e))return null;let n=o=>Promise.resolve(e.validator(o));return this.options.userinfo===void 0?n:ct(n,this.options.userinfo,e.issuer)}async validateAuth(e){let n=this.options.auth;if(!n||!("validator"in n))return null;let o=this.validatorVerifier??this.buildValidatorVerifier();if(!o)return null;let r=e.headers.authorization;if(!r||Array.isArray(r)){let s={reason:"missing_header",scheme:"bearer",source:"mcp"};return this.context.logger.debug(s,"Auth rejected: missing or malformed Authorization header"),this.context.emit("auth:rejected",s),null}let i=/^bearer\s+(.+)$/i.exec(r);if(!i){let s={reason:"unsupported_scheme",scheme:"bearer",source:"mcp"};return this.context.logger.debug(s,"Auth rejected: unsupported authorization scheme"),this.context.emit("auth:rejected",s),null}let a=i[1];try{let s=await o(a),l={subject:s.subject,scheme:s.scheme,source:"mcp"};return this.context.logger.info(l,"Auth succeeded"),this.context.emit("auth:success",l),s}catch(s){let d={reason:s instanceof Error?s.message:"invalid_token",scheme:"bearer",source:"mcp"};return ut(s)?this.context.logger.debug({err:s,...d},"Auth rejected: token expired"):this.context.logger.warn({err:s,...d},"Auth rejected: token validation failed"),this.context.emit("auth:rejected",d),null}}async setupRequestHandlers(){await this.setupRequestHandlersOn(this.server);}async setupRequestHandlersOn(e){let o=await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/types.js'),{adapterName:"mcp",packageName:"@modelcontextprotocol/sdk"}),r=o.ListToolsRequestSchema,i=o.CallToolRequestSchema;if(!r||!i)throw new Error("MCP SDK types missing ListToolsRequestSchema or CallToolRequestSchema - ensure @modelcontextprotocol/sdk is installed");let a=e;a.setRequestHandler(r,async()=>{let s=this.getAvailableTools();return this.logExposedToolsOnce(),{tools:s}}),a.setRequestHandler(i,async s=>{let d=s.params;return await this.handleToolCall(d.name||"",d.arguments||{})});}async stop(){if(this.running)try{if(this.httpServer){for(let[,n]of this.httpSessions){let o=n.transport;typeof o.close=="function"&&await o.close();}this.httpSessions.clear();let e=this.httpServer;typeof e.closeAllConnections=="function"&&e.closeAllConnections(),await new Promise(n=>{this.httpServer.close(()=>n());}),this.httpServer=null;}if(this.transport){let e=this.transport;typeof e.close=="function"&&await e.close();}this.running=!1,this.context.logger.info({},"MCP server stopped");}catch(e){let n=routecraft.isRoutecraftError(e)?e.meta.message:e instanceof Error?e.message:"Error stopping MCP server";this.context.logger.error({err:e},n);}}logExposedToolsOnce(){if(this.toolsListLogged)return;let e=this.getAvailableTools();if(e.length===0)return;let n=e.map(r=>r.name),o={tools:n,count:n.length};this.context.logger.info(o,"Exposing MCP tools"),this.context.emit("plugin:mcp:server:tools:exposed",o),this.toolsListLogged=true;}getAvailableTools(){let e=this.context.getStore(O);if(!e)return [];let n=Array.from(e.values()),o=this.options.tools;if(o)if(Array.isArray(o)){let r=new Set(o);n=n.filter(i=>r.has(i.endpoint));}else typeof o=="function"&&(n=n.filter(o));return n.map(r=>this.entryToMcpTool(r))}entryToMcpTool(e){let n={name:e.endpoint,description:e.description,inputSchema:this.schemaToJsonSchema(e.input?.body)};e.title!==void 0&&(n.title=e.title),e.output?.body!==void 0&&(n.outputSchema=this.schemaToJsonSchema(e.output.body)),e.annotations!==void 0&&(n.annotations=e.annotations);let o=e.icons??this.resolveServerIcons();return o.length>0&&(n.icons=o),n}schemaToJsonSchema(e){if(!e||typeof e!="object")return {type:"object"};let n=e["~standard"];if(n?.jsonSchema?.input)try{let o=n.jsonSchema.input({target:"draft-2020-12"});return typeof o=="object"&&o!==null?o:{type:"object"}}catch(o){return this.context.logger.debug(o,"Standard JSON Schema conversion failed"),{type:"object"}}return "~standard"in e?{type:"object",additionalProperties:true}:{type:"object"}}async handleToolCall(e,n){try{let r=this.context.getStore(O)?.get(e);if(!r){let m=new Error(`Tool not found: ${e}`);return this.context.emit("plugin:mcp:tool:failed",{tool:e,error:m.message}),{isError:!0,content:[{type:"text",text:`Error: Tool not found: ${e}`}]}}let i=typeof n=="string"?(()=>{try{return JSON.parse(n)||{}}catch{return {input:n}}})():n&&typeof n=="object"?n:{};this.context.logger.debug({bodyType:typeof i,body:i},"MCP tool call exchange body");let a=_t.getStore(),s={"routecraft.mcp.tool":e,"routecraft.mcp.session":`mcp-${Date.now()}`};a&&(s[routecraft.HeadersKeys.AUTH_PRINCIPAL]=routecraft.markAuthentic(a));let l=new routecraft.DefaultExchange(this.context,{body:i,headers:s});this.context.emit("plugin:mcp:tool:called",{tool:e,args:n});let d=await r.handler(l),c=typeof d.body=="string"?d.body:JSON.stringify(d.body);return this.context.emit("plugin:mcp:tool:completed",{tool:e}),{content:[{type:"text",text:c}]}}catch(o){let r=routecraft.isRoutecraftError(o)?o.meta.message:o instanceof Error?o.message:String(o);this.context.logger.error({tool:e,err:o},r),this.context.emit("plugin:mcp:tool:failed",{tool:e,error:r});let i=r;if(routecraft.isRoutecraftError(o)){let a=o.cause;a?.message&&(i=`${r}: ${a.message}`);}return {content:[{type:"text",text:`Error: ${i}`}],isError:true}}}};function Nt(t){if(t.transport==="http"){if(t.port!==void 0){if(typeof t.port!="number")throw new TypeError("mcpPlugin: when transport is 'http', port must be a number");if(t.port<0||t.port>65535)throw new RangeError("mcpPlugin: port must be between 0 and 65535 when transport is 'http'")}if(t.host!==void 0&&typeof t.host!="string")throw new TypeError("mcpPlugin: when provided, host must be a string")}if(t.transport==="http"&&t.cors!==void 0&&t.cors!==false){let{origin:e}=t.cors;if(!(e==="*"||typeof e=="string"||Array.isArray(e)||typeof e=="function"))throw new TypeError("mcpPlugin: cors.origin must be '*', a string, a string array, or a function")}if(t.auth!==void 0)if("provider"in t.auth){if(t.auth.provider!=="oauth")throw new TypeError('mcpPlugin: auth.provider must be "oauth". Use the oauth() helper.')}else if("validator"in t.auth){if(typeof t.auth.validator!="function")throw new TypeError("mcpPlugin: auth.validator must be a function that returns a Principal (throw to reject)")}else throw new TypeError("mcpPlugin: auth must have either a 'validator' function or 'provider' set to 'oauth'. Use jwt(), jwks(), oauth(), or a custom { validator } object.");if(t.clients){for(let[e,n]of Object.entries(t.clients))if(typeof n=="object"&&n!==null&&"transport"in n&&n.transport==="stdio"&&(!n.command||typeof n.command!="string"))throw new TypeError(`mcpPlugin: stdio client "${e}" must have a non-empty command string`)}if(t.maxRestarts!==void 0&&(typeof t.maxRestarts!="number"||!Number.isInteger(t.maxRestarts)||t.maxRestarts<0))throw new TypeError("mcpPlugin: maxRestarts must be a non-negative integer");if(t.restartDelayMs!==void 0&&(typeof t.restartDelayMs!="number"||t.restartDelayMs<=0))throw new TypeError("mcpPlugin: restartDelayMs must be a positive number");if(t.restartBackoffMultiplier!==void 0&&(typeof t.restartBackoffMultiplier!="number"||t.restartBackoffMultiplier<1))throw new TypeError("mcpPlugin: restartBackoffMultiplier must be >= 1");if(t.toolRefreshIntervalMs!==void 0&&(typeof t.toolRefreshIntervalMs!="number"||!Number.isInteger(t.toolRefreshIntervalMs)||t.toolRefreshIntervalMs<0))throw new TypeError("mcpPlugin: toolRefreshIntervalMs must be a non-negative integer")}async function $t(t,e){let n=e["~standard"];if(!n?.validate)throw new Error("mcpPlugin: schema must be a StandardSchemaV1 with ~standard.validate");let o=n.validate(t);if(o instanceof Promise&&(o=await o),o.issues)throw new Error(`mcpPlugin options validation failed: ${routecraft.formatSchemaIssues(o.issues)}`);if(o.value===void 0)throw new Error("mcpPlugin options validation failed: no value returned");return o.value}function Te(t){let e=t?.content;if(!Array.isArray(e)||e.length===0)return t;if(e.length===1){let n=e[0];if(n.type==="text"&&typeof n.text=="string")return n.text;if(typeof n.data=="string")return n.data}return e}var Se=class{constructor(e,n,o,r){this.options=e;this.logger=n;this.onEvent=o;this.onToolsUpdated=r;}options;logger;onEvent;onToolsUpdated;client=null;transport=null;running=false;stopping=false;restartCount=0;restartTimer=null;stabilityTimer=null;tools=[];async start(){if(this.running)return;this.stopping=false,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null);let e=await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/client/index.js'),{adapterName:"mcp (stdio client)",packageName:"@modelcontextprotocol/sdk"}),n=await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/client/stdio.js'),{adapterName:"mcp (stdio client)",packageName:"@modelcontextprotocol/sdk"}),{serverId:o,command:r,args:i,env:a,cwd:s}=this.options;this.transport=new n.StdioClientTransport({command:r,args:i??[],...a?{env:a}:{},...s?{cwd:s}:{},stderr:"pipe"});let l=this.transport;l.onerror=d=>{this.logger.error({err:d,serverId:o},"Stdio client transport error"),this.onEvent(`plugin:mcp:client:${o}:error`,{serverId:o,error:d});},l.onclose=()=>{this.stopping||(this.running=false,this.handleDisconnect());},l.stderr?.on&&l.stderr.on("data",d=>{this.logger.debug({serverId:o,stderr:String(d).trimEnd()},"Stdio client stderr output");}),this.client=new e.Client({name:"routecraft-mcp-client",version:"1.0.0"},{capabilities:{},listChanged:{tools:{onChanged:(d,c)=>{c&&Array.isArray(c.tools)?(this.tools=c.tools,this.onToolsUpdated(o,this.tools),this.onEvent(`plugin:mcp:client:${o}:tools:listed`,{serverId:o,toolCount:this.tools.length})):this.refreshTools();}}}}),await this.client.connect(this.transport),this.running=true,await this.refreshTools(),this.logger.info({serverId:o,toolCount:this.tools.length},"Stdio client started"),this.onEvent(`plugin:mcp:client:${o}:started`,{serverId:o,toolCount:this.tools.length});}async stop(){this.stopping=true,this.restartTimer&&(clearTimeout(this.restartTimer),this.restartTimer=null),this.stabilityTimer&&(clearTimeout(this.stabilityTimer),this.stabilityTimer=null);let{serverId:e}=this.options;if(this.client){try{await this.client.close();}catch{}this.client=null;}if(this.transport){let n=this.transport;if(typeof n.close=="function")try{await Promise.resolve(n.close());}catch{}this.transport=null;}this.running=false,this.logger.info({serverId:e},"Stdio client stopped"),this.onEvent(`plugin:mcp:client:${e}:stopped`,{serverId:e,reason:"graceful"});}async callTool(e,n){if(!this.running||!this.client)throw new Error(`Stdio client "${this.options.serverId}" is not running. Cannot call tool "${e}".`);let o=await this.client.callTool({name:e,arguments:n});return Te(o)}getTools(){return [...this.tools]}isRunning(){return this.running}async refreshTools(){if(!this.client)return;let{serverId:e}=this.options;try{let n=await this.client.listTools();this.tools=n.tools??[],this.onToolsUpdated(e,this.tools),this.onEvent(`plugin:mcp:client:${e}:tools:listed`,{serverId:e,toolCount:this.tools.length});}catch(n){this.logger.warn({err:n,serverId:e},"Failed to list tools for stdio client");}}handleDisconnect(){let{serverId:e,maxRestarts:n,restartDelayMs:o,restartBackoffMultiplier:r}=this.options;if(this.tools.length>0&&(this.tools=[],this.onToolsUpdated(e,[])),this.logger.warn({serverId:e},"Stdio client disconnected unexpectedly"),this.onEvent(`plugin:mcp:client:${e}:stopped`,{serverId:e,reason:"unexpected"}),this.restartCount>=n){this.logger.error({serverId:e,restartCount:this.restartCount,maxRestarts:n},"Stdio client exceeded max restarts, giving up"),this.onEvent(`plugin:mcp:client:${e}:error`,{serverId:e,error:new Error(`Max restarts (${n}) exceeded for stdio client "${e}"`)});return}let i=o*Math.pow(r,this.restartCount);this.logger.info({serverId:e,restartCount:this.restartCount,delayMs:i},"Scheduling stdio client restart"),this.restartTimer=setTimeout(()=>{this.restartTimer=null,this.restart();},i);}async restart(){let{serverId:e}=this.options;this.restartCount++,this.client=null,this.transport=null;try{await this.start(),this.logger.info({serverId:e,restartCount:this.restartCount},"Stdio client restarted successfully"),this.onEvent(`plugin:mcp:client:${e}:restarted`,{serverId:e,restartCount:this.restartCount});let n=this.options.restartDelayMs*2;this.stabilityTimer=setTimeout(()=>{this.stabilityTimer=null,this.running&&(this.restartCount=0);},n);}catch(n){this.logger.error({err:n,serverId:e,restartCount:this.restartCount},"Stdio client restart failed"),this.onEvent(`plugin:mcp:client:${e}:error`,{serverId:e,error:n}),this.handleDisconnect();}}};function ao(t){if(!t)return [];let e=[];return t.readOnlyHint&&e.push("read-only"),t.destructiveHint&&e.push("destructive"),t.idempotentHint&&e.push("idempotent"),t.openWorldHint&&e.push("open-world"),e}var K=class{tools=new Map;setToolsForSource(e,n,o){let r=new Map;for(let i of o){let a={name:i.name,inputSchema:i.inputSchema,source:e,transport:n};i.description!==void 0&&(a.description=i.description),i.annotations!==void 0&&(a.annotations=i.annotations);let s=ao(i.annotations);s.length>0&&(a.tags=s),r.set(i.name,a);}this.tools.set(e,r);}removeSource(e){this.tools.delete(e);}getTools(){let e=[];for(let n of this.tools.values())for(let o of n.values())e.push(o);return e}getToolsByServer(e){let n=this.tools.get(e);return n?Array.from(n.values()):[]}getTool(e){for(let n of this.tools.values()){let o=n.get(e);if(o)return o}}getToolBySource(e,n){return this.tools.get(e)?.get(n)}};var jt=new WeakMap;async function lo(t){if(typeof t=="function")return t();if(Array.isArray(t)){if(t.length===0)throw new Error("McpClientAuthOptions.token array must not be empty");let e=(jt.get(t)??0)%t.length;return jt.set(t,e+1),t[e]}return t}async function Me(t){if(!t)return;let e={},n=t.headers??{},o=Object.entries(n).find(([r])=>r.toLowerCase()==="authorization")?.[1];if(o)e.Authorization=o;else if(t.token!==void 0){let r=await lo(t.token);if(r.length===0)throw new Error("McpClientAuthOptions.token must be a non-empty string when provided");e.Authorization=`Bearer ${r}`;}for(let[r,i]of Object.entries(n))r.toLowerCase()!=="authorization"&&(e[r]=i);return Object.keys(e).length>0?e:void 0}function Ht(t){return "transport"in t&&t.transport==="stdio"}function Ae(t={}){Nt(t);let e=null,n=new Map,o=new Map,r=[],i=null;return {async apply(c){if(c.setStore(pe,true),i=new K,c.setStore(B,i),c.setStore(me,n),t.clients&&Object.keys(t.clients).length>0){let m=Object.entries(t.clients),u=new Map;for(let[p,f]of m)u.set(p,f);c.setStore(S,u);for(let[p,f]of m){if(Ht(f))await a(c,p,f,i);else {let g=f;await l(c,p,g.url,i,g.auth),d(c,p,g.url,i,g.auth);}let h=Ht(f)?"stdio":"http";c.emit(`plugin:mcp:client:${p}:registered`,{serverId:p,transport:h});}}e=new W(c,t),await e.start();},async teardown(c){for(let m of r)clearInterval(m);r.length=0;for(let[m,u]of o)try{await u.close();}catch(p){c.logger.error({err:p,serverId:m,operation:"close"},"Failed to close HTTP client");}o.clear();for(let[m,u]of n)try{await u.stop();}catch(p){c.logger.error({err:p,serverId:m,operation:"stop"},"Failed to stop stdio client");}if(n.clear(),e){try{await e.stop();}catch(m){c.logger.error({err:m,operation:"stop"},"Failed to stop MCP server plugin");}e=null;}i=null;}};async function a(c,m,u,p){let f={serverId:m,command:u.command,args:u.args??[],maxRestarts:t.maxRestarts??5,restartDelayMs:t.restartDelayMs??1e3,restartBackoffMultiplier:t.restartBackoffMultiplier??2};u.env!==void 0&&(f.env=u.env),u.cwd!==void 0&&(f.cwd=u.cwd);let h=new Se(f,c.logger,(g,R)=>{c.emit(g,R);},(g,R)=>{p.setToolsForSource(g,"stdio",R);});n.set(m,h);try{await h.start();}catch(g){c.logger.error({err:g,serverId:m,operation:"start"},"Failed to start stdio client"),c.emit(`plugin:mcp:client:${m}:error`,{serverId:m,error:g});}}async function s(c,m,u){let p=o.get(c);if(p)return p;let{Client:f}=await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/client/index.js'),{adapterName:"mcp (http client)",packageName:"@modelcontextprotocol/sdk"}),{StreamableHTTPClientTransport:h}=await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/client/streamableHttp.js'),{adapterName:"mcp (http client)",packageName:"@modelcontextprotocol/sdk"}),g=await Me(u),R=g?{requestInit:{headers:g}}:void 0,x=new h(new URL(m),R),D=new f({name:"routecraft-mcp-client",version:"1.0.0"},{capabilities:{}});await D.connect(x);let G=D;return o.set(c,G),G}async function l(c,m,u,p,f){try{let R=(await(await s(m,u,f)).listTools()).tools??[];p.setToolsForSource(m,"http",R),c.emit(`plugin:mcp:client:${m}:tools:listed`,{serverId:m,toolCount:R.length});}catch(h){o.delete(m),c.logger.warn({err:h,serverId:m,url:u,operation:"listTools"},"Failed to list tools from HTTP client");}}function d(c,m,u,p,f){let h=t.toolRefreshIntervalMs??6e4;if(h<=0)return;let g=setInterval(()=>{l(c,m,u,p,f);},h);r.push(g);}}var Oe=new Map;async function be(){let t=[...Oe.entries()];Oe.clear(),t.length!==0&&await Promise.all(t.map(async([,e])=>{try{typeof e.dispose=="function"&&await e.dispose();}catch{}}));}function co(t){return t.includes("/")?t:`Xenova/${t}`}var uo='The Hugging Face embedding provider requires "@huggingface/transformers". Install it with: bun add @huggingface/transformers';function po(t,e){if(!(t instanceof Error))return false;let n=t.message??"";return (n.includes("ERR_MODULE_NOT_FOUND")||n.includes("Cannot find module")||n.includes("Cannot find package"))&&n.includes(e)}async function mo(t){let e=co(t),n=Oe.get(e);if(n)return n.run;let o;try{o=(await import('@huggingface/transformers')).pipeline;}catch(s){throw po(s,"@huggingface/transformers")?new Error(uo):s}let r=await o("feature-extraction",e,{dtype:"fp32"}),i=(s,l)=>r(s,{pooling:l?.pooling??"mean",normalize:l?.normalize??true}),a={run:i,dispose:typeof r.dispose=="function"?()=>Promise.resolve(r.dispose()):void 0};return Oe.set(e,a),i}function Gt(t){if(t===null)return "null";if(typeof t!="object")return String(t);if(Array.isArray(t))return `array(${t.length})`;try{let e=JSON.stringify(t);return e.length>100?e.slice(0,100)+"...":e}catch{return "object"}}function fo(t){if(Array.isArray(t))return t;if(t instanceof Float32Array)return Array.from(t);if(t&&typeof t=="object"&&"data"in t){let e=t.data;if(Array.isArray(e))return e;if(e instanceof Float32Array)return Array.from(e);throw new Error(`Embedding output .data must be an Array or Float32Array; got ${typeof e}: ${Gt(e)}`)}throw new Error(`Embedding output must be an Array, Float32Array, or object with .data; got ${typeof t}: ${Gt(t)}`)}async function Vt(t){let{config:e,modelName:n,text:o}=t;if(e.provider==="mock"){let i=[];for(let a=0;a<8;a++)i.push((o.length+a)%100/100);return i}if(e.provider==="huggingface"){let i=await(await mo(n))(o,{pooling:"mean",normalize:true}),a=i&&typeof i=="object"&&"data"in i?i.data:i;return fo(a)}throw e.provider==="ollama"||e.provider==="openai"?new Error(`Embedding provider "${e.provider}" is not yet implemented. Use huggingface for now.`):new Error(`Unknown embedding provider: ${e.provider}`)}var Ee=Symbol.for("routecraft.adapter.embedding.providers"),xe=Symbol.for("routecraft.adapter.embedding.options");function go(t,e){return {...e,provider:t}}function Le(t={providers:{}}){return {apply(e){let n=new Map;for(let[o,r]of Object.entries(t.providers))r!==void 0&&n.set(o,go(o,r));e.setStore(Ee,n),t.defaultOptions&&Object.keys(t.defaultOptions).length>0&&e.setStore(xe,t.defaultOptions);},async teardown(){await be();}}}function $(t){let e=t.indexOf(":");if(e<1||e===t.length-1)throw new Error(`LLM model id must be "providerId:modelName" (e.g. ollama:lfm2.5-thinking). Got: "${t}"`);return {providerId:t.slice(0,e),modelName:t.slice(e+1)}}function Ie(t,e){if(typeof t!="string"){let a=t.modelId??"";if(a.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`LLM model: inline LlmModelConfig for provider "${t.provider}" did not resolve to a model name. Either pass the model as a "providerId:modelName" string (e.g. "${t.provider}:<model>") or set "modelId" on the config. Providers "openai", "anthropic", and "gemini" do not carry a modelId field, so those must use the string form.`});return {config:t,modelName:a}}if(!e)throw new Error(`LLM model id "${t}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store "${q.description}" can be read.`);let n=e.getStore(q);if(!n)throw new Error('LLM provider not found: no providers registered. Add llmPlugin({ providers: { ollama: { provider: "ollama" }, ... } }) to your config.');let{providerId:o,modelName:r}=$(t),i=n.get(o);if(!i)throw new Error(`LLM provider "${o}" not found. Register it with llmPlugin({ providers: { "${o}": { provider, apiKey?, baseURL? } } }).`);return {config:i,modelName:r}}function U(t,e){return t===void 0||t===""?"":typeof t=="function"?t(e):t}function De(t){let e=t.body;return typeof e=="string"?e:e==null?"":typeof e=="object"?JSON.stringify(e):String(e)}var qt={ollama:{baseURL:"http://localhost:11434/api"}};function z(t,e){throw new Error(`The ${e} LLM provider requires the "${t}" package. Install it with: bun add ${t}`)}function Y(t,e){if(!(t instanceof Error))return false;let n=t.message??"";return (n.includes("ERR_MODULE_NOT_FOUND")||n.includes("Cannot find module")||n.includes("Cannot find package"))&&n.includes(e)}function pt(t,e,n){if(t===null||typeof t!="object")throw new Error(`[${e}] Invalid model: expected an object, got ${typeof t}. Model id: ${n}`);let o=t;if(typeof o.doGenerate!="function")throw new Error(`[${e}] Invalid model: missing or invalid doGenerate method. Model id: ${n}. Ensure the provider returns an AI SDK-compatible language model.`);if(typeof o.doStream!="function")throw new Error(`[${e}] Invalid model: missing or invalid doStream method. Model id: ${n}. Ensure the provider returns an AI SDK-compatible language model.`)}function _e(t){return {...t.inputTokens!==void 0&&{inputTokens:t.inputTokens},...t.outputTokens!==void 0&&{outputTokens:t.outputTokens},...t.totalTokens!==void 0&&{totalTokens:t.totalTokens}}}function Bt(t){try{if("output"in t&&t.output!==void 0)return t.output}catch{}}function Wt(t){let e=t;if(typeof e.reasoningText=="string"&&e.reasoningText.length>0)return e.reasoningText}function Ne(t){if(t===null||typeof t!="object")return [];let e=t.steps;if(!Array.isArray(e))return [];let n=[];for(let o of e){if(o===null||typeof o!="object")continue;let r=o.toolCalls,i=o.toolResults;if(Array.isArray(r))for(let a of r){if(a===null||typeof a!="object")continue;let s=a,l=typeof s.toolCallId=="string"?s.toolCallId:"",d=typeof s.toolName=="string"?s.toolName:"",c=s.input??s.args,m={toolCallId:l,toolName:d,input:c};if(Array.isArray(i)){let u=i.find(p=>p.toolCallId===l);u&&(("output"in u||"result"in u)&&(m.output=u.output??u.result),"error"in u&&u.error!==void 0&&(m.error=u.error));}n.push(m);}}return n}function $e(t){let e={};return t.output!==void 0&&(e.output=t.output),t.tools!==void 0&&Object.keys(t.tools).length>0&&(e.tools=t.tools,t.stopWhen!==void 0&&(e.stopWhen=t.stopWhen)),t.abortSignal!==void 0&&(e.abortSignal=t.abortSignal),e}function Ue(t,e,n,o,r){let i={model:t,prompt:o,temperature:e.temperature};return e.maxTokens!==void 0&&(i.maxOutputTokens=e.maxTokens),n&&(i.system=n),e.topP!==void 0&&(i.topP=e.topP),e.frequencyPenalty!==void 0&&(i.frequencyPenalty=e.frequencyPenalty),e.presencePenalty!==void 0&&(i.presencePenalty=e.presencePenalty),{...i,...r}}async function je(t,e){switch(t.provider){case "openai":return yo(t,e);case "anthropic":return wo(t,e);case "gemini":return Ro(t,e);case "openrouter":return vo(t,e);case "ollama":return Co(t,e);default:{let n=t;throw new Error(`LLM provider not implemented: ${n.provider}`)}}}async function yo(t,e){let n;try{n=(await import('@ai-sdk/openai')).createOpenAI;}catch(i){throw Y(i,"@ai-sdk/openai")&&z("@ai-sdk/openai","OpenAI"),i}let o={apiKey:t.apiKey};return t.baseURL!==void 0&&(o.baseURL=t.baseURL),n(o)(e)}async function wo(t,e){let n;try{n=(await import('@ai-sdk/anthropic')).createAnthropic;}catch(r){throw Y(r,"@ai-sdk/anthropic")&&z("@ai-sdk/anthropic","Anthropic"),r}return n({apiKey:t.apiKey})(e)}async function Ro(t,e){let n;try{n=(await import('@ai-sdk/google')).createGoogleGenerativeAI;}catch(r){throw Y(r,"@ai-sdk/google")&&z("@ai-sdk/google","Gemini"),r}return n({apiKey:t.apiKey})(e)}async function vo(t,e){let n;try{n=(await import('@openrouter/ai-sdk-provider')).createOpenRouter;}catch(a){throw Y(a,"@openrouter/ai-sdk-provider")&&z("@openrouter/ai-sdk-provider","OpenRouter"),a}let o=n({apiKey:t.apiKey}),r=t.modelId??e,i=o.chat(r);return pt(i,"OpenRouter",r),i}async function Co(t,e){let n;try{n=(await import('ollama-ai-provider-v2')).createOllama;}catch(a){throw Y(a,"ollama-ai-provider-v2")&&z("ollama-ai-provider-v2","Ollama"),a}let o=n({baseURL:t.baseURL??qt.ollama.baseURL}),r=t.modelId??e,i=o(r);return pt(i,"Ollama",r),i}function Kt(t){if(t===null||typeof t!="object")return null;let e=t;switch(e.type){case "text-delta":{let o=Fe(e,"text")??Fe(e,"textDelta");return o===void 0||o.length===0?null:{type:"text-delta",text:o}}case "reasoning-delta":{let o=Fe(e,"text")??Fe(e,"delta");return o===void 0||o.length===0?null:{type:"reasoning-delta",text:o}}default:return null}}function Fe(t,e){let n=t[e];return typeof n=="string"?n:void 0}async function Yt(t){let{config:e,modelId:n,options:o,system:r,user:i,onDelta:a}=t,s=await je(e,n);return Po(s,o,r,i,$e(t),a)}async function Po(t,e,n,o,r,i){let{streamText:a}=await import('ai'),s=Ue(t,e,n,o,r),l=a(s);for await(let x of l.fullStream){let D=Kt(x);if(D!==null)try{await i(D);}catch(G){routecraft.logger.warn({err:G},"agent.onDelta listener threw; ignoring and continuing stream");}}let c={text:await l.text??"",raw:l},m=await J(l.usage);m&&(c.usage=_e(m));let u=await J(l.reasoningText);typeof u=="string"&&u.length>0&&(c.reasoning=u);let p=await J(l.output);p!==void 0&&(c.output=p);let f=await J(l.finishReason);typeof f=="string"&&(c.finishReason=f);let h=await J(l.steps),g=Ne({steps:h});g.length>0&&(c.toolCalls=g),Array.isArray(h)&&(c.stepsCount=h.length);let R=await J(l.response);return R&&Array.isArray(R.messages)&&(c.responseMessages=R.messages),c}async function J(t){if(t!==void 0)try{return await t}catch(e){routecraft.logger.debug({err:e},"llm.streamLlm: optional accessor rejected; treating as absent");return}}async function Jt(t){return Yt(t)}async function He(t){let{config:e,modelId:n,options:o,system:r,user:i}=t,a=await je(e,n);return ko(a,o,r,i,$e(t))}async function ko(t,e,n,o,r){let{generateText:i}=await import('ai'),a=Ue(t,e,n,o,r),s=await i(a),l={text:s.text??"",raw:s};s.usage&&(l.usage=_e(s.usage));let d=Bt(s);d!==void 0&&(l.output=d);let c=Wt(s);c&&(l.reasoning=c);let m=s.finishReason;typeof m=="string"&&(l.finishReason=m);let u=Ne(s);u.length>0&&(l.toolCalls=u);let p=s.steps;Array.isArray(p)&&(l.stepsCount=p.length);let f=s.response?.messages;return Array.isArray(f)&&(l.responseMessages=f),l}function Xt(t,e,n){let o=t["~standard"];if(!o?.validate)throw new Error(`${n} must be a StandardSchemaV1 with ~standard.validate`);let r=e==="input"?o.jsonSchema?.input:o.jsonSchema?.output,i=e==="input"?o.jsonSchema?.output:o.jsonSchema?.input,a=r?.({target:"draft-2020-12"})??i?.({target:"draft-2020-12"});if(!a||typeof a!="object")throw new Error(`${n} must expose ~standard.jsonSchema.input or .output for AI SDK use`);function s(l){let d;try{d=o.validate(l);}catch(m){return {success:false,error:m instanceof Error?m:new Error(String(m))}}return d instanceof Promise?{success:false,error:new Error(`${n}: async schema validation is not supported`)}:d.issues!=null&&(Array.isArray(d.issues)?d.issues.length>0:typeof d.issues=="object"&&d.issues!==null?Object.keys(d.issues).length>0:!!d.issues)?{success:false,error:new Error(routecraft.formatSchemaIssues(d.issues))}:{success:true,value:d.value}}return ai.jsonSchema(a,{validate:s})}function Zt(t){return Xt(t,"input","Tool input schema")}function Ge(t){let e=Xt(t,"output","LLM output schema");return ai.Output.object({schema:e})}async function Qt(t,e,n,o,r){if(t.length===0)return Object.create(null);let{tool:i}=await import('ai'),a=Object.create(null);for(let s of t){let l=s.guard,d=s.handler,c=xo(s.name,n,r);a[s.name]=i({description:s.description,inputSchema:Zt(s.input),execute:async(m,u)=>{let p={...c,abortSignal:u?.abortSignal??c.abortSignal},f=u?.toolCallId??crypto$1.randomUUID(),h=Date.now();e&&o&&e.emit(`route:${o.routeId}:agent:tool:invoked`,{routeId:o.routeId,exchangeId:o.exchangeId,correlationId:o.correlationId,toolCallId:f,toolName:s.name,input:m});try{l&&await l(m,p);let g=await d(m,p);return e&&o&&e.emit(`route:${o.routeId}:agent:tool:result`,{routeId:o.routeId,exchangeId:o.exchangeId,correlationId:o.correlationId,toolCallId:f,toolName:s.name,output:g,duration:Date.now()-h}),g}catch(g){throw e&&o&&e.emit(`route:${o.routeId}:agent:tool:error`,{routeId:o.routeId,exchangeId:o.exchangeId,correlationId:o.correlationId,toolCallId:f,toolName:s.name,error:g,duration:Date.now()-h}),g}}});}return a}function xo(t,e,n){return {logger:routecraft.logger.child({tool:t}),abortSignal:e,...n?{principal:Lo(n)}:{}}}function Lo(t){let e=routecraft.isAuthentic(t),n={...t};return n.audience&&(n.audience=[...n.audience]),n.scopes&&(n.scopes=[...n.scopes]),n.roles&&(n.roles=[...n.roles]),n.claims&&(n.claims=structuredClone(n.claims)),en(n),e?routecraft.markAuthentic(n):n}function en(t,e=new WeakSet){if(t===null||typeof t!="object"||e.has(t)||ArrayBuffer.isView(t))return t;e.add(t);for(let n of Object.keys(t)){let o=t[n];o!==null&&typeof o=="object"&&en(o,e);}return Object.freeze(t)}function nn(t,e){if(e===void 0)return;let n=t.headers[routecraft.HeadersKeys.CORRELATION_ID];return {exchangeId:t.id,correlationId:typeof n=="string"?n:t.id,routeId:e}}var Do=0,_o=1024,No=20,Ve=class{constructor(e){this.input=e;}input;async runUntilDone(e){return this.runWithValidation(e,void 0)}async runStream(e,n){return this.runWithValidation(e,n)}async runWithValidation(e,n){let{options:o,exchange:r}=this.input,i=o.validate,a=o.maxTurns??No,s=await this.prepare(e),l=0,d=this.input.user,c,m=[];try{for(;;){let u=a-l;if(u<=0)throw routecraft.rcError("RC5003",void 0,{message:c?`agent: maxTurns (${a}) reached while "validate" was still rejecting; last validator message: "${c}"`:`agent: maxTurns (${a}) reached.`});let p=await $o(s,d,u,e,n);if(l+=p.stepsCount??1,p.toolCalls&&p.toolCalls.length>0&&m.push(...p.toolCalls),!i)return this.emitFinished(p),mt(p,m);let f=await Promise.resolve(i(mt(p,m),{exchange:r,turnsUsed:l}));if(f==null)return this.emitFinished(p),mt(p,m);if(typeof f!="string"||f.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`agent: "validate" returned a non-string, non-void value (${typeof f}). Return void to accept, a non-empty string to retry.`});c=f,d=jo(this.input.user,d,p,f);}}catch(u){throw this.emitError(u),u}}emitFinished(e){let n=this.input.dispatchIdentity,o=this.input.context;if(!n||!o)return;let r=e.finishReason??"unknown";o.emit(`route:${n.routeId}:agent:finished`,{routeId:n.routeId,exchangeId:n.exchangeId,correlationId:n.correlationId,finishReason:r,...e.usage?.inputTokens!==void 0&&{inputTokens:e.usage.inputTokens},...e.usage?.outputTokens!==void 0&&{outputTokens:e.usage.outputTokens},...e.usage?.totalTokens!==void 0&&{totalTokens:e.usage.totalTokens}});}emitError(e){let n=this.input.dispatchIdentity,o=this.input.context;!n||!o||o.emit(`route:${n.routeId}:agent:error`,{routeId:n.routeId,exchangeId:n.exchangeId,correlationId:n.correlationId,error:e});}async prepare(e){let{options:n,modelConfig:o,modelName:r,tools:i,system:a,context:s,exchange:l,dispatchIdentity:d}=this.input,c=await Qt(i,s,e,d,l.principal),m={modelConfig:o,modelName:r,system:a,vercelTools:c};return n.output!==void 0?{...m,output:Ge(n.output)}:m}};async function $o(t,e,n,o,r){let i=Object.keys(t.vercelTools).length>0?{tools:t.vercelTools,stopWhen:await Uo(n)}:{},a={config:t.modelConfig,modelId:t.modelName,options:{temperature:Do,maxTokens:_o},system:t.system,user:e,abortSignal:o,...t.output!==void 0?{output:t.output}:{},...i};return r?Jt({...a,onDelta:r}):He(a)}async function Uo(t){let{stepCountIs:e}=await import('ai');return e(t)}function jo(t,e,n,o){let r=typeof e=="string"?[{role:"user",content:t}]:e,i=n.responseMessages??[];return [...r,...i,{role:"user",content:`Validator: ${o}`}]}function mt(t,e){let n={text:t.text};return t.output!==void 0&&(n.output=t.output),t.reasoning!==void 0&&(n.reasoning=t.reasoning),t.usage&&(n.usage=t.usage),e.length>0&&(n.toolCalls=e),n}function on(t,e){return t.user!==void 0?U(t.user,e):De(e)}var j=Symbol.for("routecraft.adapter.agent.registry"),X=Symbol.for("routecraft.adapter.agent.default-options");var Z=Symbol.for("routecraft.adapter.skill.registry");var Go=j.description??"routecraft.adapter.agent.registry",F=class{constructor(e){this.binding=e;}binding;adapterId="routecraft.adapter.agent";async send(e){let n=routecraft.getExchangeContext(e),o=this.resolveOptions(n),r=Vo(o,n);if(r.model===void 0)throw routecraft.rcError("RC5003",void 0,{message:'Agent: no "model" supplied and no agentPlugin({ defaultOptions: { model } }) is set on this context. Specify "model" on the agent or set a context-level default.'});let{config:i,modelName:a}=Ie(r.model,n),s=qo(r,n),l=on(r,e),d=U(r.system,e);if(d.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:'Agent: "system" resolved to an empty string. When "system" is a function, it must return a non-empty string for the incoming exchange.'});let c=Bo(d,r.skills,n),m=Wo(c,r.principal,e.principal,e),u=routecraft.getExchangeRoute(e),p=nn(e,u?.definition.id),f=new Ve({options:r,modelConfig:i,modelName:a,tools:s,user:l,system:m,context:n,exchange:e,dispatchIdentity:p}),h=u?.signal??new AbortController().signal,g=this.binding.kind==="by-name"?this.binding.perCall?.onDelta??r.onDelta:r.onDelta;return g!==void 0?await f.runStream(h,g):await f.runUntilDone(h)}resolveOptions(e){if(this.binding.kind==="inline")return this.binding.options;if(!e)throw routecraft.rcError("RC5004",void 0,{message:`Agent "${this.binding.name}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so the "${Go}" store can be read.`});let n=e.getStore(j);if(!n)throw routecraft.rcError("RC5004",void 0,{message:`Agent "${this.binding.name}" not found: no agents registered. Add agentPlugin({ agents: { "${this.binding.name}": {...} } }) to your config.`});let o=n.get(this.binding.name);if(!o){let r=Array.from(n.keys()).join(", ")||"<none>";throw routecraft.rcError("RC5004",void 0,{message:`Agent "${this.binding.name}" not found in registry. Known agents: ${r}.`})}return o}getMetadata(e){let n=e,o={};if(this.binding.kind==="by-name"&&(o.agent=this.binding.name),this.binding.kind==="inline"){let r=this.binding.options.model;typeof r=="string"&&(o.model=r);}return n.usage?.inputTokens!==void 0&&(o.inputTokens=n.usage.inputTokens),n.usage?.outputTokens!==void 0&&(o.outputTokens=n.usage.outputTokens),o}};function Vo(t,e){let n=e?.getStore(X);if(!n)return t;let o={...t};return o.model===void 0&&n.model!==void 0&&(o.model=n.model),o.tools===void 0&&n.tools!==void 0&&(o.tools=n.tools),o.maxTurns===void 0&&n.maxTurns!==void 0&&(o.maxTurns=n.maxTurns),o.principal===void 0&&n.principal!==void 0&&(o.principal=n.principal),o}function qo(t,e){if(t.tools===void 0)return [];if(!e)throw routecraft.rcError("RC5003",void 0,{message:"Agent: cannot resolve tools without a CraftContext."});return t.tools.resolve(e)}function Bo(t,e,n){if(!e||e.length===0)return t;if(!n)throw routecraft.rcError("RC5003",void 0,{message:'Agent: cannot resolve "skills" without a CraftContext.'});let o=n.getStore(Z);if(!o||o.size===0)throw routecraft.rcError("RC5003",void 0,{message:`Agent: declared "skills" (${e.map(i=>`"${i}"`).join(", ")}) but no skills are registered in this context. Install agentPlugin({ skills }) with the relevant entries.`});let r=[t];for(let i of e){let a=o.get(i);if(!a){let s=[...o.keys()].sort();throw routecraft.rcError("RC5003",void 0,{message:`Agent: unknown skill "${i}". `+(s.length>0?`Known skill names: ${s.map(l=>`"${l}"`).join(", ")}.`:"No skills are registered in this context.")})}r.push(`
2
+
3
+ ## Skill: ${a.name}
4
+
5
+ ${a.content}`);}return r.join("")}function Wo(t,e,n,o){if(e===void 0||e===false)return t;let r=typeof e=="function"?e(n,o):Ko(n);return r.trim()===""?t:`${t}
6
+
7
+ ${r}`}function Ko(t){if(!t)return `## Caller
8
+
9
+ The current request is not authenticated. No verified user identity is available. Do not assume, infer, or invent the caller's name, email, or permissions.`;let e=[];t.name&&e.push(`- Name: ${qe(t.name)}`),t.email&&e.push(`- Email: ${qe(t.email)}`),e.push(`- Subject: ${qe(t.subject)}`);let n=t.roles?.map(o=>qe(o)).filter(o=>o.length>0);return n&&n.length>0&&e.push(`- Roles: ${n.join(", ")}`),`## Caller
10
+
11
+ The current request is authenticated.
12
+ ${e.join(`
13
+ `)}`}function qe(t){return t.replace(/\s*[\r\n]+\s*/g," ").trim()}var I=Symbol.for("routecraft.adapter.fn.registry");async function Be(t,e,n,o){let i=t.getStore(me)?.get(e);if(i)try{return await i.callTool(n,o)}catch(d){throw routecraft.isRoutecraftError(d)?d:routecraft.rcError("RC5003",d,{message:`mcp dispatch: stdio call to "${e}:${n}" failed.`})}let s=t.getStore(S)?.get(e);if(!s)throw routecraft.rcError("RC5003",void 0,{message:`mcp dispatch: server "${e}" is not registered. Register it via defineConfig.mcp / mcpPlugin({ clients }).`});if(typeof s!="object"||s===null)throw routecraft.rcError("RC5003",void 0,{message:`mcp dispatch: server "${e}" config is a string shorthand and cannot be called directly. Use a full HTTP config with a url.`});if("transport"in s&&s.transport==="stdio")throw routecraft.rcError("RC5003",void 0,{message:`mcp dispatch: stdio server "${e}" is registered but its client is not running. Ensure mcpPlugin started successfully.`});let l=s;if(typeof l.url!="string"||l.url.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`mcp dispatch: server "${e}" has no url. Cannot dispatch over HTTP.`});return ft(l.url,n,o,l.auth)}async function ft(t,e,n,o){let r=await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/client/index.js'),{adapterName:"mcp (http client)",packageName:"@modelcontextprotocol/sdk"}),i=await routecraft.loadOptionalPeer(()=>import('@modelcontextprotocol/sdk/client/streamableHttp.js'),{adapterName:"mcp (http client)",packageName:"@modelcontextprotocol/sdk"}),a,s;try{let l=new URL(t),d=await Me(o),c=d?{requestInit:{headers:d}}:void 0;a=new i.StreamableHTTPClientTransport(l,c),s=new r.Client({name:"routecraft-mcp-client",version:"1.0.0"},{capabilities:{}}),await s.connect(a);let u=await s.callTool.call(s,{name:e,arguments:n});return Te(u)}catch(l){throw routecraft.isRoutecraftError(l)?l:routecraft.rcError("RC5003",l,{message:`mcp dispatch: failed to call tool "${e}" at "${t}".`})}finally{if(s){let l=s,d=l.close??l.disconnect;if(typeof d=="function")try{await Promise.resolve(d.call(s));}catch{}}if(a){let l=a,d=l.close??l.destroy;if(typeof d=="function")try{await Promise.resolve(d.call(a));}catch{}}}}var ge=Symbol.for("routecraft.ai.fn.deferred");function ee(t){return typeof t=="object"&&t!==null&&ge in t&&t[ge]===true}function er(t){let e={...t};return t.audience&&(e.audience=[...t.audience]),t.scopes&&(e.scopes=[...t.scopes]),t.roles&&(e.roles=[...t.roles]),t.claims&&(e.claims=structuredClone(t.claims)),routecraft.isAuthentic(t)?routecraft.markAuthentic(e):e}var ln={type:"object",properties:{},additionalProperties:false},cn={"~standard":{version:1,vendor:"routecraft",validate(t){return t===null||typeof t!="object"||Array.isArray(t)||Object.keys(t).length>0?{issues:[{message:"Expected an empty object {}."}]}:{value:{}}},jsonSchema:{input:()=>ln,output:()=>ln}}};function he(t,e){if(typeof t!="string"||t.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:"directTool: routeId must be a non-empty string."});let n=tr(e?.tags,t);return {[ge]:true,kind:"direct",targetId:t,...n!==void 0?{overrideTags:n}:{},resolve(o,r){let i=nr(o,t,r),a=e?.description??i.description;if(typeof a!="string"||a.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`directTool: route "${t}" has no .description() and no override was provided (referenced as fn "${r}").`});let s=e?.input??i.input?.body;if(!s)throw routecraft.rcError("RC5003",void 0,{message:`directTool: route "${t}" has no .input(...) schema and no override was provided (referenced as fn "${r}").`});let l=n??i.tags,d=((c,m)=>or(o,m,t,c));return {description:a,input:s,...l&&l.length>0?{tags:[...l]}:{},handler:d}}}}function tr(t,e){if(t===void 0)return;if(!Array.isArray(t))throw routecraft.rcError("RC5003",void 0,{message:`directTool("${e}"): override "tags" must be an array of non-empty strings.`});let n=[];for(let o of t){if(typeof o!="string"||o.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`directTool("${e}"): override "tags" must contain only non-empty strings.`});let r=o.trim();n.includes(r)||n.push(r);}return n}function nr(t,e,n){let o=t.getStore(routecraft.ADAPTER_DIRECT_REGISTRY),r=routecraft.sanitizeEndpoint(e),i=o?.get(r);if(!i){let a=o?[...o.keys()].sort():[];throw routecraft.rcError("RC5003",void 0,{message:`directTool: unknown direct route id "${e}" (referenced as fn "${n}"). `+(a.length>0?`Known route ids: ${a.join(", ")}.`:"No direct routes are registered in this context.")})}return i}async function or(t,e,n,o){let r=routecraft.sanitizeEndpoint(n),i={};e.correlationId&&(i[routecraft.HeadersKeys.CORRELATION_ID]=e.correlationId),e.principal&&(i[routecraft.HeadersKeys.AUTH_PRINCIPAL]=er(e.principal));let a=new routecraft.DefaultExchange(t,{body:o,...Object.keys(i).length>0?{headers:i}:{}});return (await routecraft.getDirectChannel(t,r,{}).send(r,a)).body}function un(){return {description:"Returns the current UTC timestamp in ISO 8601 format.",input:cn,handler:()=>new Date().toISOString(),tags:["read-only","idempotent"]}}function pn(){return {description:"Generates a fresh random UUID v4.",input:cn,handler:()=>crypto$1.randomUUID(),tags:["read-only"]}}var We=Symbol.for("routecraft.ai.tools.selection");function oe(t){return typeof t=="object"&&t!==null&&We in t&&t[We]===true}function Ke(t){if(!Array.isArray(t))throw routecraft.rcError("RC5003",void 0,{message:"tools(items): items must be an array."});return {[We]:true,resolve(e){let n=new Map;for(let r of t){if(typeof r=="string"){if(gn(r)&&!mn(e,r)){for(let a of hn(e,r,void 0))n.set(a.name,a);continue}let i=fn(e,r,void 0);n.set(i.name,i);continue}if(r===null||typeof r!="object")throw routecraft.rcError("RC5003",void 0,{message:"tools(): each item must be a string, { name, guard?, description? }, or { tagged, from?, guard? }."});if("name"in r){if(typeof r.name!="string"||r.name.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:"tools(): { name } must be a non-empty string."});if(gn(r.name)&&!mn(e,r.name)){if(r.description!==void 0)throw routecraft.rcError("RC5003",void 0,{message:`tools(): { name: "${r.name}", description } is not supported for MCP tools. The MCP server is the source of truth for description and schema; do not override.`});for(let s of hn(e,r.name,r.guard))n.set(s.name,s);continue}if(r.description!==void 0&&(typeof r.description!="string"||r.description.trim()===""))throw routecraft.rcError("RC5003",void 0,{message:`tools(): { name: "${r.name}", description } must be a non-empty string when present.`});let i=fn(e,r.name,r.guard),a=r.description!==void 0?{...i,description:r.description}:i;n.set(a.name,a);}else if(!("tagged"in r))throw routecraft.rcError("RC5003",void 0,{message:'tools(): each object item must include "name" or "tagged".'})}let o=new Map(n);for(let r of t)if(typeof r=="object"&&r!==null&&"tagged"in r){let i=cr(r.tagged);if(i.length===0)continue;let a=lr(e,i,r.guard,r.from);if(a.length===0)throw routecraft.rcError("RC5003",void 0,{message:r.from?`tools(): tagged selector matched no tools (tagged: ${yn(i)}, from: "${r.from}").`:`tools(): tagged selector matched no tools (tagged: ${yn(i)}).`});for(let s of a)o.has(s.name)||o.set(s.name,s);}return [...o.values()]}}}function mn(t,e){return t.getStore(I)?.has(e)??false}function fn(t,e,n){if(typeof e!="string"||e.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:"tools(): tool name must be a non-empty string."});let r=t.getStore(I)?.get(e);if(r)return rr(t,e,r,n);let i=/^Direct\((.*)\)$/.exec(e);if(i){let s=i[1].trim();if(s==="")throw routecraft.rcError("RC5003",void 0,{message:`tools(): "${e}" has an empty route id; use "Direct(<routeId>)".`});let l=`direct_${s}`,c=he(s).resolve(t,l);return ne(l,c,n)}let a=ur(t);throw routecraft.rcError("RC5003",void 0,{message:`tools(): unknown tool "${e}". `+(a.length>0?`Available: ${a.join(", ")}.`:"No fns or direct routes are registered in this context.")})}function rr(t,e,n,o){if(ee(n)){let r=n.resolve(t,e);return ne(e,r,o)}return ne(e,n,o)}function ne(t,e,n){return {name:t,description:e.description,input:e.input,...e.tags&&e.tags.length>0?{tags:e.tags}:{},...n?{guard:n}:{},handler:e.handler}}function gn(t){return t.startsWith("mcp__")?true:t.startsWith("MCP(")&&t.endsWith(")")}function ir(t){if(t.startsWith("MCP(")&&t.endsWith(")")){let e=t.slice(4,-1).trim(),n=e.indexOf(":"),o=n===-1?e:e.slice(0,n).trim(),r=n===-1?"*":e.slice(n+1).trim();if(o===""||r==="")throw routecraft.rcError("RC5003",void 0,{message:`tools(): MCP reference "${t}" must use "MCP(server:tool)" or "MCP(server)"; got an empty server or tool segment.`});return {clientName:o,toolName:r}}if(t.startsWith("mcp__")){let e=t.slice(5),n=e.indexOf("__"),o=n===-1?e:e.slice(0,n),r=n===-1?"*":e.slice(n+2);if(o.trim()===""||r.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`tools(): MCP reference "${t}" must use "mcp__server__tool" or "mcp__server"; got an empty server or tool segment.`});return {clientName:o,toolName:r}}throw routecraft.rcError("RC5003",void 0,{message:`tools(): MCP reference "${t}" must use "MCP(server:tool)", "MCP(server)", or the raw "mcp__server__tool" form.`})}function hn(t,e,n){let{clientName:o,toolName:r}=ir(e),i=t.getStore(B);if(!i)throw routecraft.rcError("RC5003",void 0,{message:`tools(): MCP reference "${e}" but no MCP_TOOL_REGISTRY is present. Install mcpPlugin (defineConfig.mcp) so external clients populate the registry.`});let a=i.getToolsByServer(o);if(a.length===0){let l=Rn(i);throw routecraft.rcError("RC5003",void 0,{message:`tools(): MCP reference "${e}" but client "${o}" has no registered tools. `+(l.length>0?`Known MCP clients: ${l.map(d=>`"${d}"`).join(", ")}.`:"No MCP clients are registered in this context.")})}if(r==="*")return a.map(l=>gt(t,l,n));let s=a.find(l=>l.name===r);if(!s){let l=a.map(d=>d.name).sort();throw routecraft.rcError("RC5003",void 0,{message:`tools(): MCP reference "${e}" but tool "${r}" is not registered under client "${o}". Known tools on "${o}": ${l.map(d=>`"${d}"`).join(", ")}.`})}return [gt(t,s,n)]}function gt(t,e,n){let o=`mcp__${e.source}__${e.name}`,r=e.description&&e.description.trim()!==""?e.description:`MCP tool "${e.name}" on client "${e.source}".`,i=sr(e.inputSchema),s={name:o,description:r,input:i,handler:async l=>{if(l==null||typeof l!="object"||Array.isArray(l))throw routecraft.rcError("RC5003",void 0,{message:`mcp tool "${o}" expects an object argument; received ${l===null?"null":Array.isArray(l)?"array":typeof l}.`});let d=l;return Be(t,e.source,e.name,d)}};return e.tags&&e.tags.length>0&&(s.tags=[...e.tags]),n&&(s.guard=n),s}function sr(t){return {"~standard":{version:1,vendor:"routecraft",validate(e){return {value:e}},jsonSchema:{input:()=>t,output:()=>t}}}}function Rn(t){let e=new Set;for(let n of t.getTools())e.add(n.source);return [...e].sort()}function ar(t){if(t===void 0)return {kind:"all"};if(typeof t!="string"||t.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:'tools(): "from" must be a non-empty string when present.'});if(t.startsWith("mcp__")){let e=t.slice(5);if(e.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`tools(): from "${t}" has an empty server name; use "mcp__<server>".`});return {kind:"mcp",mcpClient:e}}throw routecraft.rcError("RC5003",void 0,{message:`tools(): from "${t}" is not a supported source filter. Use "mcp__<server>".`})}function lr(t,e,n,o){let r=new Set(e),i=ar(o),a=[],s=new Set,l=new Set;if(i.kind==="all"){let c=t.getStore(I);if(c)for(let[u,p]of c){if(ee(p)){if(p.kind!=="direct"||!(p.overrideTags??dr(t,p.targetId)).some(R=>r.has(R)))continue;let g=p.resolve(t,u);a.push(ne(u,g,n)),s.add(u),l.add(routecraft.sanitizeEndpoint(p.targetId));continue}(p.tags??[]).some(h=>r.has(h))&&(a.push(ne(u,p,n)),s.add(u));}let m=t.getStore(routecraft.ADAPTER_DIRECT_REGISTRY);if(m)for(let[u,p]of m){if(l.has(u)||!(p.tags??[]).some(x=>r.has(x)))continue;let h=`direct_${u}`;if(s.has(h)||typeof p.description!="string"||p.description.trim()===""||!p.input?.body)continue;let R=he(u).resolve(t,h);a.push(ne(h,R,n)),s.add(h);}}let d=t.getStore(B);if(d){let c;if(i.kind==="mcp"){if(c=d.getToolsByServer(i.mcpClient),c.length===0){let m=Rn(d);throw routecraft.rcError("RC5003",void 0,{message:`tools(): from "mcp__${i.mcpClient}" has no registered tools. `+(m.length>0?`Known MCP clients: ${m.map(u=>`"${u}"`).join(", ")}.`:"No MCP clients are registered in this context.")})}}else c=d.getTools();for(let m of c){if(!(m.tags??[]).some(f=>r.has(f)))continue;let p=gt(t,m,n);s.has(p.name)||(a.push(p),s.add(p.name));}}else if(i.kind==="mcp")throw routecraft.rcError("RC5003",void 0,{message:`tools(): from "mcp__${i.mcpClient}" but no MCP_TOOL_REGISTRY is present. Install mcpPlugin (defineConfig.mcp).`});return a}function yn(t){return t.length===1?`"${t[0]}"`:`[${t.map(e=>`"${e}"`).join(", ")}]`}function dr(t,e){return t.getStore(routecraft.ADAPTER_DIRECT_REGISTRY)?.get(routecraft.sanitizeEndpoint(e))?.tags??[]}function cr(t){return (Array.isArray(t)?t:[t]).filter(e=>typeof e=="string"&&e.trim()!=="")}function ur(t){let e=[...(t.getStore(I)??new Map).keys()],n=[...(t.getStore(routecraft.ADAPTER_DIRECT_REGISTRY)??new Map).keys()].map(o=>`Direct(${o})`);return [...e,...n].sort()}function wt(t){if(typeof t.system=="string"){if(t.system.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:'Agent: "system" is required and must be a non-empty string (or a function that returns one).'})}else if(typeof t.system!="function")throw routecraft.rcError("RC5003",void 0,{message:'Agent: "system" must be a string or a function (exchange) => string.'});if(t.user!==void 0&&typeof t.user!="string"&&typeof t.user!="function")throw routecraft.rcError("RC5003",void 0,{message:'Agent: "user" must be a string or a function (exchange) => string when present.'});if(t.model!==void 0){if(typeof t.model!="string"||t.model.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:'Agent: "model" must be a non-empty "providerId:modelName" string when present.'});try{$(t.model);}catch{throw routecraft.rcError("RC5003",void 0,{message:`Agent: "model" string must be in "providerId:modelName" form (e.g. ollama:llama3). Got: "${t.model}"`})}}if(t.tools!==void 0&&!oe(t.tools))throw routecraft.rcError("RC5003",void 0,{message:'Agent: "tools" must be the result of tools([...]).'});if(t.principal!==void 0&&typeof t.principal!="boolean"&&typeof t.principal!="function")throw routecraft.rcError("RC5003",void 0,{message:'Agent: "principal" must be a boolean or a function (principal, exchange) => string when present.'});if(t.output!==void 0){if(t.output===null||typeof t.output!="object")throw routecraft.rcError("RC5003",void 0,{message:'Agent: "output" must be a Standard Schema (Zod/Valibot/ArkType/etc.).'});if(typeof t.output["~standard"]?.validate!="function")throw routecraft.rcError("RC5003",void 0,{message:'Agent: "output" must be a Standard Schema (Zod/Valibot/ArkType/etc.).'})}}function ze(t,e){if(typeof t=="string"){if(t.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:"Agent: name must be a non-empty string."});return routecraft.tagAdapter(new F({kind:"by-name",name:t,...e?{perCall:e}:{}}),ze,e?routecraft.factoryArgs(t,e):routecraft.factoryArgs(t))}return wt(t),routecraft.tagAdapter(new F({kind:"inline",options:t}),ze,routecraft.factoryArgs(t))}function Cn(t,e){if(e===null||typeof e!="object")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: fn "${t}" entry must be an object with description, input, and handler.`});if(typeof e.description!="string"||e.description.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: fn "${t}" is missing a non-empty "description".`});if(e.input===null||typeof e.input!="object"||typeof e.input["~standard"]!="object")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: fn "${t}" "input" is required and must be a Standard Schema value (Zod/Valibot/ArkType/etc.).`});if(typeof e.input["~standard"]?.validate!="function")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: fn "${t}" "input" must be a Standard Schema with a callable validate.`});if(typeof e.handler!="function")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: fn "${t}" "handler" is required and must be a function.`});if(e.tags!==void 0){if(!Array.isArray(e.tags))throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: fn "${t}" "tags" must be an array of non-empty strings.`});for(let o=0;o<e.tags.length;o++){let r=e.tags[o];if(typeof r!="string"||r.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: fn "${t}" "tags" must contain only non-empty strings.`});e.tags[o]=r.trim();}}}function pr(t,e){if(typeof e.description!="string"||e.description.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: agent "${t}" is missing a non-empty "description". Registered agents carry their own description because they are not backed by a route.`});wt(e);}function Ye(t={}){let e=t.agents??{},n=t.functions??{},o=t.skills??{},r=mr(t.defaultOptions);return {apply(i){let a=i.getStore(j),s=a??new Map;for(let[u,p]of Object.entries(e)){if(u.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:"agentPlugin: agent id must be a non-empty string."});if(p===null||typeof p!="object")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: agent "${u}" entry must be an object with description, model, and system.`});if(p.tools!==void 0&&!oe(p.tools))throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: agent "${u}" "tools" must be the result of tools([...]).`});if(pr(u,p),s.has(u))throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: duplicate agent id "${u}". Each agent id must be unique within a context.`});s.set(u,p);}a||i.setStore(j,s);let l=i.getStore(I),d=l??new Map;for(let[u,p]of Object.entries(n)){if(u.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:"agentPlugin: fn id must be a non-empty string."});if(p===null||typeof p!="object")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: fn "${u}" entry must be an object with description, input, and handler.`});if(ee(p)||Cn(u,p),d.has(u))throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: duplicate fn id "${u}". Each fn id must be unique within a context.`});d.set(u,p);}l||i.setStore(I,d);let c=i.getStore(Z),m=c??new Map;for(let[u,p]of Object.entries(o)){if(typeof u!="string"||u.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:"agentPlugin: skill name must be a non-empty string."});if(p===null||typeof p!="object")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: skill "${u}" entry must be an object with name, description, and content.`});if(p.name!==u)throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: skill key "${u}" does not match its "name" field "${String(p.name)}". Keys and names must match so the registry has one canonical id per skill.`});if(typeof p.description!="string"||p.description.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: skill "${u}" is missing a non-empty "description".`});if(typeof p.content!="string"||p.content.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: skill "${u}" is missing non-empty "content". Skills inject their content into the agent's system prompt; an empty content would not change behaviour.`});if(m.has(u))throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: duplicate skill name "${u}". Each skill name must be unique within a context.`});m.set(u,p);}if(!c&&m.size>0&&i.setStore(Z,m),r!==void 0){let u=i.getStore(X),p=fr(u,r);i.setStore(X,p);}}}}function mr(t){if(t!==void 0){if(t===null||typeof t!="object"||Array.isArray(t))throw routecraft.rcError("RC5003",void 0,{message:'agentPlugin: "defaultOptions" must be an object with optional "model" / "tools".'});if(t.model!==void 0){if(typeof t.model!="string"||t.model.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:'agentPlugin: "defaultOptions.model" must be a non-empty "providerId:modelName" string.'});try{$(t.model);}catch{throw routecraft.rcError("RC5003",void 0,{message:`agentPlugin: "defaultOptions.model" must be in "providerId:modelName" form (e.g. anthropic:claude-opus-4-7). Got: "${t.model}"`})}}if(t.tools!==void 0&&!oe(t.tools))throw routecraft.rcError("RC5003",void 0,{message:'agentPlugin: "defaultOptions.tools" must be the result of tools([...]).'});return t}}function fr(t,e){if(!t)return {...e};if(e.model!==void 0&&t.model!==void 0)throw routecraft.rcError("RC5003",void 0,{message:'agentPlugin: "defaultOptions.model" is already set on this context. A context can have only one default model.'});if(e.tools!==void 0&&t.tools!==void 0)throw routecraft.rcError("RC5003",void 0,{message:'agentPlugin: "defaultOptions.tools" is already set on this context. Combine selectors into a single tools([...]) call.'});return {...t,...e.model!==void 0?{model:e.model}:{},...e.tools!==void 0?{tools:e.tools}:{}}}routecraft.registerConfigApplier("llm",t=>ve(t));routecraft.registerConfigApplier("mcp",t=>Ae(t));routecraft.registerConfigApplier("embedding",t=>Le(t));routecraft.registerConfigApplier("agent",t=>Ye(t));var Pn={McpAdapter:Symbol.for("routecraft.ai.McpAdapter")};function gr(t,e){return typeof t=="object"&&t!==null&&t[e]===true}function hr(t){return gr(t,Pn.McpAdapter)}async function wr(t,e){let n;try{n=JSON.parse(t);}catch{return}let o=e["~standard"];if(!o?.validate)return;let r=o.validate(n);if(r instanceof Promise&&(r=await r),!(r&&typeof r=="object"&&"issues"in r&&r.issues))return r&&typeof r=="object"&&"value"in r?r.value:void 0}var Rr=0,vr=1024,re=class{constructor(e,n={}){this.modelId=e;this.options=n;}modelId;adapterId="routecraft.adapter.llm";options;mergedOptions(e){let n=e.getStore(ue);return {temperature:Rr,maxTokens:vr,...n,...this.options}}async send(e){let n=routecraft.getExchangeContext(e),{config:o,modelName:r}=Ie(this.modelId,n),i=this.mergedOptions(n),a=U(i.system,e),s=U(i.user,e)||De(e),l={temperature:i.temperature,maxTokens:i.maxTokens};i.topP!==void 0&&(l.topP=i.topP),i.frequencyPenalty!==void 0&&(l.frequencyPenalty=i.frequencyPenalty),i.presencePenalty!==void 0&&(l.presencePenalty=i.presencePenalty);let d=i.output!==void 0?Ge(i.output):void 0,c=await He({config:o,modelId:r,options:l,system:a,user:s,output:d});if(c.output===void 0&&c.text&&i.output!==void 0){let m=await wr(c.text,i.output);m!==void 0&&(c.output=m);}return c}getMetadata(e){let n=e,{providerId:o}=$(this.modelId),r={model:this.modelId,provider:o};return n.usage&&(n.usage.inputTokens!==void 0&&(r.inputTokens=n.usage.inputTokens),n.usage.outputTokens!==void 0&&(r.outputTokens=n.usage.outputTokens)),r}};function kn(t,e){return new re(t,e)}var ie=Symbol.for("routecraft.mcp.adapter");var Cr=/^[A-Za-z0-9_-]{1,64}$/;function Pr(t){if(!Cr.test(t))throw routecraft.rcError("RC5003",void 0,{message:`Invalid MCP tool name "${t}"`,suggestion:"MCP tool names must match /^[A-Za-z0-9_-]{1,64}$/ for client interoperability (OpenAI, Anthropic, etc.). Use alphanumerics, underscore, or hyphen in the route's .id()."})}var Ze=class{adapterId="routecraft.adapter.mcp";options;constructor(e={}){this[ie]=true,this.options=e;}async subscribe(e,n,o,r,i){if(!i?.routeId)throw routecraft.rcError("RC5003",void 0,{message:"McpSourceAdapter requires a route id from the engine (missing SourceMeta.routeId)",suggestion:"MCP source adapters take their tool name from the route id. Call .id('tool-name') on the route before .from(mcp(...))."});let a=i.routeId;Pr(a);let s=i.discovery,l=s?.description;if(typeof l!="string"||l.length===0)throw routecraft.rcError("RC5003",void 0,{message:`MCP route "${a}" requires a description`,suggestion:"Set .description('...') on the route builder before .from(mcp()); the MCP protocol requires a non-empty description for each tool."});if(e.getStore(pe)!==true)throw new Error("MCP plugin required: routes using .from(mcp(...)) require the MCP plugin. Add mcpPlugin() to your config: plugins: [mcpPlugin()].");let c=e.getStore(O);if(c||(c=new Map,e.setStore(O,c)),c.has(a))throw routecraft.rcError("RC5003",void 0,{message:`Duplicate MCP tool endpoint "${a}": another .from(mcp(...)) route already registered this endpoint in the same context`,suggestion:"Each MCP tool endpoint must be unique within a context. Rename one of the mcp() routes to a different route id."});let u={endpoint:a,description:l,handler:async p=>n(p.body,p.headers,void 0,void 0,p.principal)};s?.title!==void 0&&(u.title=s.title),s?.input!==void 0&&(u.input=s.input),s?.output!==void 0&&(u.output=s.output),this.options.annotations!==void 0&&(u.annotations=this.options.annotations),this.options.icons!==void 0&&(u.icons=this.options.icons),o.signal.addEventListener("abort",()=>{e.getStore(O)?.delete(a);},{once:true}),!o.signal.aborted&&(c.set(a,u),r?.(),await new Promise(p=>{if(o.signal.aborted){p();return}o.signal.addEventListener("abort",()=>p(),{once:true});}));}};function Tr(t){let e=t.trim().toLowerCase();if(!e.startsWith("http://")&&!e.startsWith("https://"))throw new Error(`MCP client: url must be HTTP or HTTPS. Stdio is not supported in routes; register stdio clients via mcpPlugin({ clients: { name: { command, args } } }). Got: "${t.slice(0,50)}${t.length>50?"...":""}"`)}function Sr(t,e){if(!t.serverId||!e)return;let o=e.getStore(S)?.get(t.serverId);if(!(o&&typeof o=="object"&&"transport"in o))return o}function Mr(t,e){if(t.url)return Tr(t.url),{url:t.url,auth:t.auth};if(t.serverId&&!e)throw new Error(`MCP client: serverId "${t.serverId}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store "${String(S)}" can be read.`);if(t.serverId&&e){let n=Sr(t,e);if(!n)throw new Error(`MCP client: serverId "${t.serverId}" not found in context store. Register it with context store key "${String(S)}".`);let o=typeof n=="string"?n:n.url,r=t.auth??(typeof n=="object"&&"auth"in n?n.auth:void 0);return {url:o,auth:r}}throw new Error("MCP client: either url or serverId must be provided in McpClientOptions.")}var Qe=t=>typeof t.body=="object"&&t.body!==null?t.body:{input:t.body},ye=class{constructor(e){this.options=e;if(this[ie]=true,!e.url&&!e.serverId)throw new Error("MCP client: either url or serverId must be provided in McpClientOptions.");if(e.url&&e.serverId)throw new Error("MCP client: cannot provide both url and serverId. Use either url for direct HTTP or serverId for registered servers.")}options;adapterId="routecraft.adapter.mcp";async send(e){let n=routecraft.getExchangeContext(e),o=this.options.tool??(typeof e.body=="object"&&e.body!==null&&"tool"in e.body&&typeof e.body.tool=="string"?e.body.tool:void 0);if(!o)throw new Error("MCP client: tool name required. Set options.tool or exchange.body.tool.");let i=(this.options.args??Qe)(e);if(this.options.serverId){if(!n)throw new Error(`MCP client: serverId "${this.options.serverId}" requires a context to resolve. Ensure the exchange has context (e.g. from a route).`);let d=Ar(n,this.options.serverId),c=await Be(n,this.options.serverId,o,i);return c&&typeof c=="object"&&(c.metadata={toolName:o,transport:d,serverId:this.options.serverId}),c}let{url:a,auth:s}=Mr(this.options,n),l=await ft(a,o,i,s);return l&&typeof l=="object"&&(l.metadata={toolName:o,url:a,transport:"http"}),l}getMetadata(e){return e&&typeof e=="object"&&"metadata"in e?e.metadata:{toolName:"unknown",transport:"unknown"}}};function Ar(t,e){let o=t.getStore(S)?.get(e);return o&&typeof o=="object"&&"transport"in o&&o.transport==="stdio"?"stdio":"http"}function we(t,e){if(typeof t=="object"&&t!==null&&("url"in t||"serverId"in t)){let n=t;if(typeof n.auth?.token=="string"&&n.auth.token.trim().length===0)throw new TypeError("mcp(): auth.token must be a non-empty string when provided");if(Array.isArray(n.auth?.token)){if(n.auth.token.length===0)throw new TypeError("mcp(): auth.token array must not be empty");for(let o=0;o<n.auth.token.length;o++){let r=n.auth.token[o];if(typeof r!="string"||r.trim().length===0)throw new TypeError(`mcp(): auth.token[${o}] must be a non-empty string`)}}return routecraft.tagAdapter(new ye(n),we,routecraft.factoryArgs(t,e))}if(typeof t=="string"&&t.includes(":")){let n=t.indexOf(":"),o=t.slice(0,n),r=t.slice(n+1),i={serverId:o,tool:r};return e!==void 0&&typeof e=="object"&&"args"in e&&e.args!==void 0&&(i.args=e.args),routecraft.tagAdapter(new ye(i),we,routecraft.factoryArgs(t,e))}if(typeof t=="string")throw routecraft.rcError("RC5003",void 0,{message:`mcp(${JSON.stringify(t)}) is not a valid call: a bare string without ":" is neither a client shorthand nor source options`,suggestion:"Use .from(mcp()) for a source (tool name comes from .id()), .to(mcp({ url, tool })) for a remote server, .to(mcp('server:tool')) for a registered shorthand, or direct('name') for in-process dispatch."});return routecraft.tagAdapter(new Ze(t??{}),we,routecraft.factoryArgs(t,e))}function br(t){if(typeof t=="function")return async n=>t(n);let e=t;return async n=>n===e.client_id?e:void 0}function Er(t){if(!t)throw new TypeError("oauth: `verify` is required. Pass jwks(...), jwt(...), or a custom (token) => OAuthPrincipal function.");return typeof t=="function"?async e=>t(e):async e=>t.validator(e)}function Tn(t){if(!t.verify)throw new TypeError("oauth: `verify` is required. Pass jwks(...), jwt(...), or a custom (token) => OAuthPrincipal function.");let e=Er(t.verify),n=br(t.client),o=typeof t.verify=="function"?void 0:t.verify.issuer;return {provider:"oauth",endpoints:t.endpoints,verifyAccessToken:e,getClient:n,...o!==void 0&&{issuer:o},...t.baseUrl!==void 0&&{baseUrl:t.baseUrl},...t.requiredScopes!==void 0&&{requiredScopes:t.requiredScopes}}}var et;async function Ir(){if(et)return et;try{return et=(await import('yaml')).parse,et}catch(t){throw t instanceof Error&&(t.message.includes("ERR_MODULE_NOT_FOUND")||t.message.includes("Cannot find module")||t.message.includes("Cannot find package"))&&t.message.includes("yaml")?new Error('The markdown loaders (agents()/skills()) require the "yaml" package. Install it with: bun add yaml'):t}}async function kt(t,e){let n=path.basename(e,path.extname(e));if(!t.startsWith("---"))return {path:e,filename:n,frontmatter:{},body:t.trim()};let o=t.indexOf(`
14
+ ---`,3);if(o===-1)throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${e}": opened a YAML front-matter block with "---" but never closed it. Add a closing "---" line before the body.`});let r=t.slice(3,o).trim(),i=t.slice(o+4).trim(),a;try{r?a=(await Ir())(r):a={};}catch(s){throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${e}": YAML front matter failed to parse. ${s.message}`})}if(a!==null&&typeof a!="object")throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${e}": YAML front matter must parse to an object (got ${typeof a}).`});return {path:e,filename:n,frontmatter:a??{},body:i}}async function tt(t){let e=path.resolve(process.cwd(),t),n;try{n=fs.readFileSync(e,"utf-8");}catch(o){throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${t}" could not be read: ${o.message}`})}return kt(n,e)}async function nt(t,e={}){let n=path.resolve(process.cwd(),t),o;try{o=fs.statSync(n);}catch(i){throw routecraft.rcError("RC5003",void 0,{message:`Markdown directory "${t}" could not be opened: ${i.message}`})}if(!o.isDirectory())throw routecraft.rcError("RC5003",void 0,{message:`Markdown directory "${t}" is not a directory. Pass a path to a directory containing .md files.`});let r=[];for(let i of fs.readdirSync(n,{withFileTypes:true})){if(i.isFile()){if(path.extname(i.name).toLowerCase()!==".md")continue;r.push(await kt(fs.readFileSync(path.join(n,i.name),"utf-8"),path.join(n,i.name)));continue}if(i.isDirectory()&&e.sentinelFilename){let a=path.join(n,i.name,e.sentinelFilename),s;try{s=fs.statSync(a);}catch{continue}if(!s.isFile())continue;let l=await kt(fs.readFileSync(a,"utf-8"),a);l.filename=i.name,r.push(l);}}return r.sort((i,a)=>i.filename.localeCompare(a.filename)),r}function se(t,e,n){if(typeof t!="string"||t.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${n}": frontmatter field "${e}" must be a non-empty string.`});return t}function Tt(t,e,n){if(t!==void 0){if(!Array.isArray(t))throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${n}": frontmatter field "${e}" must be an array of strings.`});for(let o of t)if(typeof o!="string"||o.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${n}": frontmatter field "${e}" must contain only non-empty strings.`});return t}}function On(t,e,n){if(t!==void 0){if(typeof t!="boolean")throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${n}": frontmatter field "${e}" must be a boolean (true or false).`});return t}}function bn(t,e,n){if(t!==void 0){if(typeof t!="number"||!Number.isFinite(t)||!Number.isInteger(t)||t<1)throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${n}": frontmatter field "${e}" must be a positive integer.`});return t}}var En=new Set(["name","description","model","maxTurns","tools","skills","principal"]);function Dr(t,e,n,o){for(let u of Object.keys(e))if(!En.has(u))throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${o}": frontmatter field "${u}" is not yet supported. Currently supported fields: ${[...En].sort().join(", ")}.`});let r=se(e.name,"name",o);if(r!==t)throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${o}": frontmatter "name" ("${r}") must match the filename ("${t}"). Rename one or the other.`});let i=se(e.description,"description",o);if(n.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${o}": agent body is empty. The body becomes the agent's system prompt; an empty system prompt is rejected at dispatch.`});let a=e.model;if(a!==void 0&&typeof a!="string")throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${o}": frontmatter "model" must be a string of the form "provider:model" (e.g. "anthropic:claude-sonnet-4-6").`});if(typeof a=="string"&&!a.includes(":"))throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${o}": frontmatter "model" ("${a}") must use the full "provider:model" form. Bare model aliases like "sonnet" / "opus" / "haiku" are not yet supported by the markdown loader.`});let s=bn(e.maxTurns,"maxTurns",o),l=Tt(e.tools,"tools",o),d=Tt(e.skills,"skills",o),c=On(e.principal,"principal",o),m={description:i,system:n};return a&&(m.model=a),s!==void 0&&(m.maxTurns=s),l!==void 0&&(m.tools=Ke(l)),d!==void 0&&(m.skills=d),c!==void 0&&(m.principal=c),{name:r,agent:m}}function _r(t,e){if(!e)return t;let n={...t};return e.description!==void 0&&(n.description=e.description),e.model!==void 0&&(n.model=e.model),e.maxTurns!==void 0&&(n.maxTurns=e.maxTurns),e.tools!==void 0&&(n.tools=e.tools),e.skills!==void 0&&(n.skills=e.skills),e.principal!==void 0&&(n.principal=e.principal),e.system!==void 0&&(n.system=e.system),n}async function xn(t,e={}){let n={},o=t.endsWith(".md")?[await tt(t)]:await nt(t);for(let r of o){let{name:i,agent:a}=Dr(r.filename,r.frontmatter,r.body,r.path);n[i]=_r(a,e[i]);}for(let r of Object.keys(e))if(!(r in n))throw routecraft.rcError("RC5003",void 0,{message:`agents("${t}"): override for "${r}" but no agent with that name was loaded from disk.`});return n}var ot=class extends Error{name="SuspendError";reason;resumeChannel;constructor(e){super(e?.reason?`Agent suspended: ${e.reason}`:"Agent suspended pending external resumption."),e?.reason!==void 0&&(this.reason=e.reason),e?.resumeChannel!==void 0&&(this.resumeChannel=e.resumeChannel);}};function Nr(t,e,n,o){let r=se(e.name,"name",o);if(r!==t)throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${o}": frontmatter "name" ("${r}") must match the filename ("${t}"). Rename one or the other.`});let i=se(e.description,"description",o);if(n.trim()==="")throw routecraft.rcError("RC5003",void 0,{message:`Markdown file "${o}": skill body is empty. The body becomes the injected skill content; an empty body would not change the agent's behaviour.`});return {name:r,description:i,content:n}}async function Ln(t,e={}){let n={},o=new Map,r=t.endsWith(".md")?[await tt(t)]:await nt(t,{sentinelFilename:"SKILL.md"});for(let i of r){let a=Nr(i.filename,i.frontmatter,i.body,i.path),s=o.get(a.name);if(s)throw routecraft.rcError("RC5003",void 0,{message:`skills("${t}"): duplicate skill name "${a.name}" loaded from both "${s}" and "${i.path}". Each skill name must be unique within a directory; rename or remove one source.`});o.set(a.name,i.path);let l=e[a.name];n[a.name]=l?{...a,...l}:a;}for(let i of Object.keys(e))if(!(i in n))throw routecraft.rcError("RC5003",void 0,{message:`skills("${t}"): override for "${i}" but no skill with that name was loaded from disk.`});return n}function Ur(t){let e=t.indexOf(":");if(e<1||e===t.length-1)throw new Error(`Embedding adapter: model id must be "providerId:modelName" (e.g. huggingface:all-MiniLM-L6-v2). Got: "${t}"`);return {providerId:t.slice(0,e),modelName:t.slice(e+1)}}function jr(t,e){if(!e)throw new Error(`Embedding adapter: model id "${t}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so embedding providers can be read.`);let n=e.getStore(Ee);if(!n)throw new Error("Embedding provider not found: no providers registered. Add embeddingPlugin({ providers: { huggingface: {} } }) to your config.");let{providerId:o,modelName:r}=Ur(t),i=n.get(o);if(!i)throw new Error(`Embedding provider "${o}" not found. Register it with embeddingPlugin({ providers: { "${o}": {} } }).`);return {config:i,modelName:r}}function Fr(t){return e=>{let n=t(e);return Array.isArray(n)?n.filter(Boolean).join(" | "):n}}var le=class{constructor(e,n){this.modelId=e;this.options=n;}modelId;adapterId="routecraft.adapter.embedding";options;mergedOptions(e){return {...e.getStore(xe),...this.options}}async send(e){let n=routecraft.getExchangeContext(e),{config:o,modelName:r}=jr(this.modelId,n),i=this.mergedOptions(n),s=Fr(i.using)(e);return {embedding:await Vt({config:o,modelName:r,text:s})}}};function In(t,e){return new le(t,e)}Object.defineProperty(exports,"jwks",{enumerable:true,get:function(){return routecraft.jwks}});Object.defineProperty(exports,"jwt",{enumerable:true,get:function(){return routecraft.jwt}});exports.AgentDestinationAdapter=F;exports.BRAND=Pn;exports.EmbeddingDestinationAdapter=le;exports.LlmDestinationAdapter=re;exports.MCP_LOCAL_TOOL_REGISTRY=O;exports.McpHeadersKeys=Ce;exports.McpServer=W;exports.McpToolRegistry=K;exports.SuspendError=ot;exports.agent=ze;exports.agentPlugin=Ye;exports.agents=xn;exports.currentTime=un;exports.defaultArgs=Qe;exports.directTool=he;exports.disposeEmbeddingPipelineCache=be;exports.embedding=In;exports.embeddingPlugin=Le;exports.isMcpAdapter=hr;exports.isOAuthAuth=Pe;exports.llm=kn;exports.llmPlugin=ve;exports.mcp=we;exports.mcpPlugin=Ae;exports.oauth=Tn;exports.randomUuid=pn;exports.skills=Ln;exports.tools=Ke;exports.validateWithSchema=$t;//# sourceMappingURL=index.cjs.map
3
15
  //# sourceMappingURL=index.cjs.map