@frontmcp/observability 1.11.1 → 1.11.3

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
@@ -82,13 +82,13 @@ const shutdown = setupOTel({ serviceName: 'help-desk', exporter: 'otlp', endpoin
82
82
 
83
83
  ### Options
84
84
 
85
- | Option | Type | Default | Description |
86
- | ------------- | ----------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------- |
87
- | `tracing` | `boolean \| TracingOptions` | `true` | Spans for requests and calls, and `this.telemetry` in tools, resources and prompts |
88
- | `logging` | `boolean \| { sinks, redactFields, includeStacks, staticFields }` | `false` | Structured log entries, sent to `sinks`. `logging: true` has no sinks and writes nothing |
89
- | `requestLogs` | `boolean \| { maxEntries, includeSummaries, onRequestComplete }` | `false` | One object per HTTP request, passed to `onRequestComplete`. `includeSummaries` isn't read yet |
85
+ | Option | Type | Default | Description |
86
+ | ------------- | ----------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
87
+ | `tracing` | `boolean \| TracingOptions` | `true` | Spans for requests and calls, and `this.telemetry` in tools, resources and prompts |
88
+ | `logging` | `boolean \| { sinks, redactFields, includeStacks, staticFields }` | `false` | Structured log entries, sent to `sinks`. Without `sinks` (`logging: true` included), one JSON object per line on stdout (stderr over stdio; the console in a browser) |
89
+ | `requestLogs` | `boolean \| { maxEntries, includeSummaries, onRequestComplete }` | `false` | One object per HTTP request, passed to `onRequestComplete`. `includeSummaries: true` adds `input_summary` and `output_summary`: argument names, result keys, content types and sizes, never values |
90
90
 
91
- `TracingOptions` turns span groups on or off: `httpSpans`, `executionSpans`, `fetchSpans`, `transportSpans`, `authSpans`, `oauthSpans`, `elicitationSpans`, `flowStageEvents` and `startupReport` default to `true`, and `hookSpans` (a span for each hook, verbose) to `false`.
91
+ `TracingOptions` turns span groups on or off: `httpSpans`, `executionSpans`, `fetchSpans`, `transportSpans`, `authSpans`, `oauthSpans`, `elicitationSpans`, `flowStageEvents` and `startupReport` default to `true`, and `hookSpans` (a span for each hook, verbose) to `false`. `authSpans` gives each HTTP request an `auth session:verify` span, with `frontmcp.auth.result` (`authorized`, `anonymous`, `unauthorized`, `forbidden` or `error`).
92
92
 
93
93
  The log sinks are `{ type: 'stdout', pretty? }` (one JSON object per line), `{ type: 'console' }` (a readable line), `{ type: 'callback', fn }`, `{ type: 'otlp', endpoint?, headers?, batchSize?, flushIntervalMs?, serviceName? }`, `{ type: 'pino', logger }` and `{ type: 'winston', logger }`.
94
94
 
package/esm/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
2
2
  const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
3
3
  // __frontmcpCreateRequire
4
- var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __require=(x=>typeof require!=="undefined"?require:typeof Proxy!=="undefined"?new Proxy(x,{get:(a,b)=>(typeof require!=="undefined"?require:a)[b]}):x)(function(x){if(typeof require!=="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+x+'" is not supported')});var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var __decorateClass=(decorators,target,key,kind)=>{var result=kind>1?void 0:kind?__getOwnPropDesc(target,key):target;for(var i=decorators.length-1,decorator;i>=0;i--)if(decorator=decorators[i])result=(kind?decorator(target,key,result):decorator(result))||result;if(kind&&result)__defProp(target,key,result);return result};var winston_sink_exports={};__export(winston_sink_exports,{WinstonSink:()=>WinstonSink});function mapToWinstonLevel(level){switch(level){case"debug":case"verbose":return"debug";case"info":return"info";case"warn":return"warn";case"error":return"error";default:return"info"}}var WinstonSink;var init_winston_sink=__esm({"libs/observability/src/logging/sinks/winston.sink.ts"(){"use strict";WinstonSink=class{constructor(logger){this.logger=logger}write(entry){const{message,level,...meta}=entry;const winstonLevel=mapToWinstonLevel(level);switch(winstonLevel){case"debug":this.logger.debug(message,meta);break;case"info":this.logger.info(message,meta);break;case"warn":this.logger.warn(message,meta);break;case"error":this.logger.error(message,meta);break}}}}});var pino_sink_exports={};__export(pino_sink_exports,{PinoSink:()=>PinoSink});function mapToPinoLevel(level){switch(level){case"debug":case"verbose":return"debug";case"info":return"info";case"warn":return"warn";case"error":return"error";default:return"info"}}var PinoSink;var init_pino_sink=__esm({"libs/observability/src/logging/sinks/pino.sink.ts"(){"use strict";PinoSink=class{constructor(logger){this.logger=logger}write(entry){const{message,level,...obj}=entry;const pinoLevel=mapToPinoLevel(level);switch(pinoLevel){case"debug":this.logger.debug(obj,message);break;case"info":this.logger.info(obj,message);break;case"warn":this.logger.warn(obj,message);break;case"error":this.logger.error(obj,message);break}}}}});var otlp_sink_exports={};__export(otlp_sink_exports,{OtlpSink:()=>OtlpSink});var OtlpSink;var init_otlp_sink=__esm({"libs/observability/src/logging/sinks/otlp.sink.ts"(){"use strict";OtlpSink=class{constructor(options){this.batch=[];let base=options.endpoint;while(base.endsWith("/")){base=base.slice(0,-1)}this.endpoint=`${base}/v1/logs`;this.headers={"Content-Type":"application/json",...options.headers??{}};this.batchSize=options.batchSize??100;this.maxQueueSize=options.maxQueueSize??5e3;this.serviceName=options.serviceName??(typeof process!=="undefined"?process.env?.["OTEL_SERVICE_NAME"]:void 0)??"frontmcp-server";const flushMs=options.flushIntervalMs??5e3;if(flushMs>0){this.flushTimer=setInterval(()=>{void this.flush()},flushMs);if(this.flushTimer&&typeof this.flushTimer==="object"&&"unref"in this.flushTimer){this.flushTimer.unref()}}}write(entry){this.batch.push(entry);this.enforceCapacity();if(this.batch.length>=this.batchSize){void this.flush()}}async flush(){if(this.batch.length===0)return;const entries=this.batch.splice(0);const payload=this.buildOtlpPayload(entries);try{const controller=new AbortController;const timeout=setTimeout(()=>controller.abort(),1e4);try{const response=await fetch(this.endpoint,{method:"POST",headers:this.headers,body:JSON.stringify(payload),signal:controller.signal});clearTimeout(timeout);if(!response.ok){const body=await response.text().catch(()=>"");console.error(`[OtlpSink] Export failed: HTTP ${response.status} \u2014 ${body.slice(0,200)}`);this.requeue(entries)}}catch(err){clearTimeout(timeout);console.debug(`[OtlpSink] Export error (${entries.length} entries): ${err instanceof Error?err.message:err}`);this.requeue(entries)}}catch{}}requeue(entries){this.batch.unshift(...entries);this.enforceCapacity()}enforceCapacity(){if(this.batch.length>this.maxQueueSize){this.batch.splice(0,this.batch.length-this.maxQueueSize)}}async close(){if(this.flushTimer){clearInterval(this.flushTimer);this.flushTimer=void 0}await this.flush()}buildOtlpPayload(entries){return{resourceLogs:[{resource:{attributes:[{key:"service.name",value:{stringValue:this.serviceName}}]},scopeLogs:[{scope:{name:"@frontmcp/observability"},logRecords:entries.map(entry=>this.entryToLogRecord(entry))}]}]}}entryToLogRecord(entry){const attrs=[];const record={timeUnixNano:String(new Date(entry.timestamp).getTime()*1e6),severityNumber:entry.severity_number,severityText:entry.level.toUpperCase(),body:{stringValue:entry.message},attributes:attrs};if(entry.trace_id){record.traceId=entry.trace_id}if(entry.span_id){record.spanId=entry.span_id}if(entry.trace_flags!==void 0){record.flags=entry.trace_flags}if(entry.request_id){attrs.push({key:"frontmcp.request.id",value:{stringValue:entry.request_id}})}if(entry.session_id_hash){attrs.push({key:"mcp.session.id",value:{stringValue:entry.session_id_hash}})}if(entry.scope_id){attrs.push({key:"frontmcp.scope.id",value:{stringValue:entry.scope_id}})}if(entry.flow_name){attrs.push({key:"frontmcp.flow.name",value:{stringValue:entry.flow_name}})}if(entry.prefix){attrs.push({key:"log.prefix",value:{stringValue:entry.prefix}})}if(entry.elapsed_ms!==void 0){attrs.push({key:"elapsed_ms",value:Number.isInteger(entry.elapsed_ms)?{intValue:String(entry.elapsed_ms)}:{doubleValue:entry.elapsed_ms}})}if(entry.error){attrs.push({key:"error.type",value:{stringValue:entry.error.type}});attrs.push({key:"error.message",value:{stringValue:entry.error.message}});if(entry.error.code){attrs.push({key:"error.code",value:{stringValue:entry.error.code}})}if(entry.error.error_id){attrs.push({key:"error.id",value:{stringValue:entry.error.error_id}})}if(entry.error.stack){attrs.push({key:"error.stack",value:{stringValue:entry.error.stack}})}}if(entry.attributes){for(const[key,value]of Object.entries(entry.attributes)){if(value==null)continue;if(typeof value==="string"){attrs.push({key,value:{stringValue:value}})}else if(typeof value==="number"){attrs.push({key,value:Number.isInteger(value)?{intValue:String(value)}:{doubleValue:value}})}else if(typeof value==="boolean"){attrs.push({key,value:{boolValue:value}})}else{attrs.push({key,value:{stringValue:JSON.stringify(value)}})}}}return record}}}});import{trace as trace6}from"@opentelemetry/api";import{AgentCallHook,DynamicPlugin,FlowHooksOf as FlowHooksOf2,FRONTMCP_CONTEXT as FRONTMCP_CONTEXT2,FRONTMCP_LOGGER,HttpHook,ListResourcesHook,ListResourceTemplatesHook,ListToolsHook,Plugin,ProviderScope,ResourceHook as ResourceHook2,ToolHook as ToolHook2}from"@frontmcp/sdk";function defaultStream(){const flag=typeof process!=="undefined"?process.env?.["FRONTMCP_STDIO"]:void 0;return flag==="1"||flag==="true"?process.stderr:process.stdout}var StdoutSink=class{constructor(options){this.stream=options?.stream??defaultStream();this.pretty=options?.pretty??false}write(entry){const line=this.pretty?JSON.stringify(entry,null,2):JSON.stringify(entry);this.stream.write(line+"\n")}};var ConsoleSink=class{write(entry){const method=levelToConsoleMethod(entry.level);const formatted=formatEntry(entry);method(formatted)}};function formatEntry(entry){const useAnsi=typeof process!=="undefined"&&!!process.stdout?.isTTY;const ts=entry.timestamp.slice(11,23);const level=entry.level.toUpperCase().padEnd(7);const traceShort=entry.trace_id?entry.trace_id.slice(0,8):"";const reqShort=entry.request_id?entry.request_id.slice(0,8):"";const parts=[];const DIM2=useAnsi?"\x1B[2m":"";const BOLD2=useAnsi?"\x1B[1m":"";const RESET2=useAnsi?"\x1B[0m":"";const levelColor=useAnsi?LEVEL_COLORS[entry.level]??"":"";parts.push(`${DIM2}[${ts}]${RESET2}`);parts.push(`${BOLD2}${levelColor}${level}${RESET2}`);if(traceShort||reqShort){parts.push(`${DIM2}[${traceShort}${reqShort?":"+reqShort:""}]${RESET2}`)}if(entry.prefix)parts.push(`${DIM2}[${entry.prefix}]${RESET2}`);parts.push(entry.message);if(entry.attributes&&Object.keys(entry.attributes).length>0){const attrs=Object.entries(entry.attributes).map(([k,v])=>`${k}=${typeof v==="string"?v:JSON.stringify(v)}`).join(" ");parts.push(`${DIM2}{ ${attrs} }${RESET2}`)}if(entry.error){parts.push(`[${entry.error.type}: ${entry.error.message}]`)}if(entry.elapsed_ms!==void 0){parts.push(`${DIM2}(${entry.elapsed_ms}ms)${RESET2}`)}return parts.join(" ")}var LEVEL_COLORS={debug:"\x1B[34m",verbose:"\x1B[90m",info:"\x1B[32m",warn:"\x1B[33m",error:"\x1B[31m"};function levelToConsoleMethod(level){switch(level){case"debug":case"verbose":return console.debug;case"info":return console.info;case"warn":return console.warn;case"error":return console.error;default:return console.log}}var CallbackSink=class{constructor(fn){this.fn=fn}write(entry){this.fn(entry)}};function createSink(config){switch(config.type){case"stdout":return new StdoutSink({stream:config.stream,pretty:config.pretty});case"console":return new ConsoleSink;case"winston":{const{WinstonSink:WinstonSink2}=(init_winston_sink(),__toCommonJS(winston_sink_exports));return new WinstonSink2(config.logger)}case"pino":{const{PinoSink:PinoSink2}=(init_pino_sink(),__toCommonJS(pino_sink_exports));return new PinoSink2(config.logger)}case"callback":return new CallbackSink(config.fn);case"otlp":{const{OtlpSink:OtlpSink2}=(init_otlp_sink(),__toCommonJS(otlp_sink_exports));return new OtlpSink2({endpoint:config.endpoint??(typeof process!=="undefined"?process.env?.["OTEL_EXPORTER_OTLP_ENDPOINT"]:void 0)??"http://localhost:4318",headers:config.headers,batchSize:config.batchSize,flushIntervalMs:config.flushIntervalMs,serviceName:config.serviceName})}default:throw new Error(`Unknown sink type: ${config.type}`)}}function createSinks(configs){if(configs&&configs.length>0){return configs.map(createSink)}return[]}import{LogLevelName,LogTransport,LogTransportInterface}from"@frontmcp/sdk";import{redactFields}from"@frontmcp/utils";var LOG_LEVEL_TO_OTEL_SEVERITY={debug:5,verbose:6,info:9,warn:13,error:17};var StructuredLogTransport=class extends LogTransportInterface{constructor(sinks,options,contextAccessor){super();this.sinks=sinks;this.redactFieldNames=options?.redactFields??[];this.includeStacks=options?.includeStacks??true;this.staticFields=options?.staticFields??{};this.getContext=contextAccessor}log(rec){const entry=this.buildEntry(rec);if(this.onEntry){try{this.onEntry(entry)}catch{}}for(const sink of this.sinks){try{sink.write(entry)}catch{}}}buildEntry(rec){const levelName=LogLevelName[rec.level]??"info";const entry={...this.staticFields,timestamp:rec.timestamp.toISOString(),level:levelName,severity_number:LOG_LEVEL_TO_OTEL_SEVERITY[levelName]??9,message:String(rec.message)};if(rec.prefix){entry.prefix=rec.prefix}const ctx=this.getContext?.();if(ctx){entry.trace_id=ctx.traceContext.traceId;entry.span_id=ctx.traceContext.parentId;entry.trace_flags=ctx.traceContext.traceFlags;entry.request_id=ctx.requestId;entry.session_id_hash=ctx.sessionIdHash;entry.scope_id=ctx.scopeId;if(ctx.flowName){entry.flow_name=ctx.flowName}entry.elapsed_ms=ctx.elapsed}this.processArgs(rec.args,entry);return entry}processArgs(args,entry){const attributes={};let hasAttributes=false;for(const arg of args){if(arg instanceof Error){entry.error=this.buildError(arg)}else if(typeof arg==="object"&&arg!==null&&!Array.isArray(arg)){const obj=arg;const redacted=this.redactFieldNames.length>0?redactFields(obj,this.redactFieldNames):obj;Object.assign(attributes,redacted);hasAttributes=true}}if(hasAttributes){entry.attributes=attributes}}buildError(err){const result={type:err.constructor.name,message:err.message};if("code"in err&&typeof err.code==="number"){result.code=String(err.code)}if("errorId"in err&&typeof err.errorId==="string"){result.error_id=err.errorId}if(this.includeStacks&&err.stack){result.stack=err.stack}return result}};StructuredLogTransport=__decorateClass([LogTransport({name:"StructuredLogTransport",description:"Produces structured log objects and forwards to configurable sinks"})],StructuredLogTransport);var OTEL_TRACER=Symbol.for("frontmcp:observability:otel-tracer");var OTEL_CONFIG=Symbol.for("frontmcp:observability:otel-config");var RequestLogCollector=class{constructor(context,options){this.entries=[];this.hooksTriggered=new Set;this.authenticated=false;this.status="ok";this.finalized=false;this.requestId=context.requestId;this.traceId=context.traceId;this.sessionIdHash=context.sessionIdHash;this.scopeId=context.scopeId;this.startTime=new Date;this.maxEntries=options?.maxEntries??500;this.onComplete=options?.onRequestComplete}addEntry(entry){if(this.finalized||this.entries.length>=this.maxEntries)return;const logEntry={timestamp:entry.timestamp,level:entry.level,message:entry.message};if(entry.flow_name){logEntry.stage=entry.flow_name}if(entry.elapsed_ms!==void 0){logEntry.elapsed_ms=entry.elapsed_ms}if(entry.attributes&&Object.keys(entry.attributes).length>0){logEntry.attributes=entry.attributes}this.entries.push(logEntry)}addHook(stage){this.hooksTriggered.add(stage)}setHttpInfo(method,path){this.httpMethod=method;this.httpPath=path}setRpcMethod(method){this.rpcMethod=method}setToolName(name){this.toolName=name}setResourceUri(uri){this.resourceUri=uri}setPromptName(name){this.promptName=name}setAuthInfo(type,authenticated){this.authType=type;this.authenticated=authenticated}setStatus(status,statusCode){this.status=status;this.statusCode=statusCode}setStatusCode(statusCode){this.statusCode=statusCode;if(statusCode>=400)this.status="error"}setError(error){this.error=error;this.status="error"}async finalize(){if(this.finalized){return this.finalizedLog}this.finalized=true;const log=this.toRequestLog();this.finalizedLog=log;if(this.onComplete){try{await this.onComplete(log)}catch{}}return log}toRequestLog(){const endTime=new Date;return{request_id:this.requestId,trace_id:this.traceId,session_id_hash:this.sessionIdHash,scope_id:this.scopeId,start_time:this.startTime.toISOString(),end_time:endTime.toISOString(),duration_ms:endTime.getTime()-this.startTime.getTime(),http_method:this.httpMethod,http_path:this.httpPath,rpc_method:this.rpcMethod,tool_name:this.toolName,resource_uri:this.resourceUri,prompt_name:this.promptName,auth_type:this.authType,authenticated:this.authenticated,status:this.status,status_code:this.statusCode,error:this.error,hooks_triggered:Array.from(this.hooksTriggered),entries:[...this.entries]}}isFinalized(){return this.finalized}getEntryCount(){return this.entries.length}};import{isAnonymousSubject}from"@frontmcp/sdk";import{context as otelContext3,SpanKind as SpanKind12,SpanStatusCode as SpanStatusCode2,trace as trace3}from"@opentelemetry/api";import{addHookObserver,FlowControl,InternalMcpError,toMcpError}from"@frontmcp/sdk";import{sha256Hex}from"@frontmcp/utils";var McpAttributes={METHOD_NAME:"mcp.method.name",SESSION_ID:"mcp.session.id",RESOURCE_URI:"mcp.resource.uri",COMPONENT_TYPE:"mcp.component.type",COMPONENT_KEY:"mcp.component.key"};var FrontMcpAttributes={SCOPE_ID:"frontmcp.scope.id",SERVER_NAME:"frontmcp.server.name",TOOL_NAME:"frontmcp.tool.name",TOOL_OWNER:"frontmcp.tool.owner",RESOURCE_URI:"frontmcp.resource.uri",RESOURCE_NAME:"frontmcp.resource.name",PROMPT_NAME:"frontmcp.prompt.name",FLOW_NAME:"frontmcp.flow.name",FLOW_STAGE:"frontmcp.flow.stage",HOOK_STAGE:"frontmcp.hook.stage",HOOK_OWNER:"frontmcp.hook.owner",SESSION_ID_HASH:"frontmcp.session.id_hash",AUTH_TYPE:"frontmcp.auth.type",REQUEST_ID:"frontmcp.request.id",PROVIDER_TYPE:"frontmcp.provider.type",DELEGATE_ORIGINAL_NAME:"frontmcp.delegate.original_name",TRANSPORT_TYPE:"frontmcp.transport.type",TRANSPORT_REQUEST_TYPE:"frontmcp.transport.request_type",SESSION_PROTOCOL:"frontmcp.session.protocol",SESSION_CREATED:"frontmcp.session.created",AUTH_MODE:"frontmcp.auth.mode",AUTH_RESULT:"frontmcp.auth.result",OAUTH_GRANT_TYPE:"frontmcp.oauth.grant_type",ELICITATION_ID:"frontmcp.elicitation.id",AGENT_NAME:"frontmcp.agent.name",AGENT_ITERATIONS:"frontmcp.agent.iterations",AGENT_EXECUTION_DURATION_MS:"frontmcp.agent.execution_duration_ms",STARTUP_TOOLS_COUNT:"frontmcp.startup.tools_count",STARTUP_RESOURCES_COUNT:"frontmcp.startup.resources_count",STARTUP_PROMPTS_COUNT:"frontmcp.startup.prompts_count",STARTUP_PLUGINS_COUNT:"frontmcp.startup.plugins_count",STARTUP_DURATION_MS:"frontmcp.startup.duration_ms"};var HttpAttributes={METHOD:"http.request.method",STATUS_CODE:"http.response.status_code",URL_PATH:"url.path",URL_FULL:"url.full",URL_SCHEME:"url.scheme",SERVER_ADDRESS:"server.address",SERVER_PORT:"server.port"};var RpcAttributes={SYSTEM:"rpc.system",SERVICE:"rpc.service",METHOD:"rpc.method",JSONRPC_VERSION:"rpc.jsonrpc.version",JSONRPC_REQUEST_ID:"rpc.jsonrpc.request_id"};var EnduserAttributes={ID:"enduser.id",SCOPE:"enduser.scope"};import{SpanKind as SpanKind2}from"@opentelemetry/api";import{SpanKind,SpanStatusCode,context as otelContext,trace}from"@opentelemetry/api";function startSpan(tracer,options){const parentCtx=options.parentContext??otelContext.active();const span=tracer.startSpan(options.name,{kind:options.kind??SpanKind.INTERNAL,attributes:options.attributes},parentCtx);const spanContext=trace.setSpan(parentCtx,span);return{span,context:spanContext}}function endSpanOk(span){span.setStatus({code:SpanStatusCode.OK});span.end()}function endSpanError(span,error){const message=typeof error==="string"?error:error.message;span.setStatus({code:SpanStatusCode.ERROR,message});if(error instanceof Error){span.recordException(error)}span.end()}async function withSpan(tracer,options,fn){const{span,context:spanContext}=startSpan(tracer,options);return otelContext.with(spanContext,async()=>{try{const result=await fn(span);endSpanOk(span);return result}catch(err){endSpanError(span,err instanceof Error?err:String(err));throw err}})}function startAuthSpan(tracer,options){return startSpan(tracer,{name:`auth ${options.flowName}`,kind:SpanKind2.INTERNAL,attributes:{[FrontMcpAttributes.FLOW_NAME]:options.flowName},parentContext:options.parentContext})}function setAuthMode(span,mode){span.setAttribute(FrontMcpAttributes.AUTH_MODE,mode)}function setAuthResult(span,result){span.setAttribute(FrontMcpAttributes.AUTH_RESULT,result)}import{SpanKind as SpanKind3}from"@opentelemetry/api";function startFetchSpan(tracer,options){return startSpan(tracer,{name:options.method.toUpperCase(),kind:SpanKind3.CLIENT,attributes:{[HttpAttributes.METHOD]:options.method.toUpperCase(),[HttpAttributes.URL_FULL]:options.url},parentContext:options.parentContext})}function setFetchResponseStatus(span,statusCode){span.setAttribute(HttpAttributes.STATUS_CODE,statusCode)}import{SpanKind as SpanKind4}from"@opentelemetry/api";function recordHookEvent(parentSpan,stage,owner){const attributes={};if(owner){attributes[FrontMcpAttributes.HOOK_OWNER]=owner}parentSpan.addEvent(`hook.${stage}`,attributes)}function startHookSpan(tracer,options){const attributes={[FrontMcpAttributes.HOOK_STAGE]:options.stage};if(options.owner){attributes[FrontMcpAttributes.HOOK_OWNER]=options.owner}if(options.flowName){attributes[FrontMcpAttributes.FLOW_NAME]=options.flowName}return startSpan(tracer,{name:`hook ${options.stage}`,kind:SpanKind4.INTERNAL,attributes,parentContext:options.parentContext})}import{SpanKind as SpanKind5}from"@opentelemetry/api";function startHttpServerSpan(tracer,options){const attributes={[HttpAttributes.METHOD]:options.method.toUpperCase(),[HttpAttributes.URL_PATH]:options.path};if(options.scheme){attributes[HttpAttributes.URL_SCHEME]=options.scheme}if(options.serverAddress){attributes[HttpAttributes.SERVER_ADDRESS]=options.serverAddress}if(options.serverPort){attributes[HttpAttributes.SERVER_PORT]=options.serverPort}if(options.scopeId){attributes[FrontMcpAttributes.SCOPE_ID]=options.scopeId}if(options.requestId){attributes[FrontMcpAttributes.REQUEST_ID]=options.requestId}return startSpan(tracer,{name:`${options.method.toUpperCase()} ${options.path}`,kind:SpanKind5.SERVER,attributes,parentContext:options.parentContext})}function setHttpResponseStatus(span,statusCode){span.setAttribute(HttpAttributes.STATUS_CODE,statusCode)}import{SpanKind as SpanKind6}from"@opentelemetry/api";function startPromptSpan(tracer,options){return startSpan(tracer,{name:`prompt ${options.name}`,kind:SpanKind6.INTERNAL,attributes:{[FrontMcpAttributes.PROMPT_NAME]:options.name,[McpAttributes.COMPONENT_TYPE]:"prompt",[McpAttributes.COMPONENT_KEY]:`prompt:${options.name}`},parentContext:options.parentContext})}import{SpanKind as SpanKind7}from"@opentelemetry/api";function startResourceSpan(tracer,options){const attributes={[FrontMcpAttributes.RESOURCE_URI]:options.uri,[McpAttributes.RESOURCE_URI]:options.uri,[McpAttributes.COMPONENT_TYPE]:"resource",[McpAttributes.COMPONENT_KEY]:`resource:${options.uri}`};if(options.name){attributes[FrontMcpAttributes.RESOURCE_NAME]=options.name}return startSpan(tracer,{name:`resource ${options.uri}`,kind:SpanKind7.INTERNAL,attributes,parentContext:options.parentContext})}import{SpanKind as SpanKind8}from"@opentelemetry/api";function startRpcSpan(tracer,options){const attributes={[RpcAttributes.SYSTEM]:"mcp",[RpcAttributes.METHOD]:options.method,[RpcAttributes.JSONRPC_VERSION]:"2.0",[McpAttributes.METHOD_NAME]:options.method};if(options.requestId!==void 0){attributes[RpcAttributes.JSONRPC_REQUEST_ID]=String(options.requestId)}if(options.scopeId){attributes[FrontMcpAttributes.SCOPE_ID]=options.scopeId}if(options.serviceName){attributes[RpcAttributes.SERVICE]=options.serviceName;attributes[FrontMcpAttributes.SERVER_NAME]=options.serviceName}if(options.sessionIdHash){attributes[McpAttributes.SESSION_ID]=options.sessionIdHash;attributes[FrontMcpAttributes.SESSION_ID_HASH]=options.sessionIdHash}return startSpan(tracer,{name:options.method,kind:SpanKind8.SERVER,attributes,parentContext:options.parentContext})}import{SpanKind as SpanKind9}from"@opentelemetry/api";function emitStartupReport(tracer,data){const attributes={[FrontMcpAttributes.STARTUP_TOOLS_COUNT]:data.toolsCount,[FrontMcpAttributes.STARTUP_RESOURCES_COUNT]:data.resourcesCount,[FrontMcpAttributes.STARTUP_PROMPTS_COUNT]:data.promptsCount,[FrontMcpAttributes.STARTUP_PLUGINS_COUNT]:data.pluginsCount,[FrontMcpAttributes.STARTUP_DURATION_MS]:data.durationMs};if(data.scopeId){attributes[FrontMcpAttributes.SCOPE_ID]=data.scopeId}const{span}=startSpan(tracer,{name:"frontmcp.startup",kind:SpanKind9.INTERNAL,attributes});endSpanOk(span)}import{SpanKind as SpanKind10}from"@opentelemetry/api";function startToolSpan(tracer,options){const attributes={[FrontMcpAttributes.TOOL_NAME]:options.name,[McpAttributes.COMPONENT_TYPE]:"tool",[McpAttributes.COMPONENT_KEY]:`tool:${options.name}`};if(options.owner){attributes[FrontMcpAttributes.TOOL_OWNER]=options.owner}if(options.enduserId){attributes[EnduserAttributes.ID]=options.enduserId}if(options.enduserScope){attributes[EnduserAttributes.SCOPE]=options.enduserScope}return startSpan(tracer,{name:`tool ${options.name}`,kind:SpanKind10.INTERNAL,attributes,parentContext:options.parentContext})}import{SpanKind as SpanKind11}from"@opentelemetry/api";function startTransportSpan(tracer,options){const attributes={[FrontMcpAttributes.TRANSPORT_TYPE]:options.type};if(options.sessionIdHash){attributes[FrontMcpAttributes.SESSION_ID_HASH]=options.sessionIdHash}if(options.sessionCreated!==void 0){attributes[FrontMcpAttributes.SESSION_CREATED]=options.sessionCreated}return startSpan(tracer,{name:`transport ${options.type}`,kind:SpanKind11.INTERNAL,attributes,parentContext:options.parentContext})}function setTransportRequestType(span,requestType){span.setAttribute(FrontMcpAttributes.TRANSPORT_REQUEST_TYPE,requestType)}import{TraceFlags,trace as trace2,context as otelContext2}from"@opentelemetry/api";function frontmcpToOTelSpanContext(tc){return{traceId:tc.traceId,spanId:tc.parentId,traceFlags:tc.traceFlags&TraceFlags.SAMPLED?TraceFlags.SAMPLED:TraceFlags.NONE,isRemote:true}}function otelToFrontmcpContext(sc){const flags=sc.traceFlags.toString(16).padStart(2,"0");return{traceId:sc.traceId,parentId:sc.spanId,traceFlags:sc.traceFlags,raw:`00-${sc.traceId}-${sc.spanId}-${flags}`}}function createOTelContextFromTrace(tc){const spanContext=frontmcpToOTelSpanContext(tc);const span=trace2.wrapSpanContext(spanContext);return trace2.setSpan(otelContext2.active(),span)}var SPAN_KEY=Symbol.for("frontmcp:otel:span");var SPAN_CTX_KEY=Symbol.for("frontmcp:otel:span-ctx");var EXEC_SPAN_KEY=Symbol.for("frontmcp:otel:exec-span");var ACTIVE_SPAN_KEY=Symbol.for("frontmcp:otel:active-span");var ACTIVE_OTEL_CTX_KEY=Symbol.for("frontmcp:otel:active-otel-ctx");var STAGE_TS_KEY=Symbol.for("frontmcp:otel:stage-ts");var STAGE_EVENTS_KEY=Symbol.for("frontmcp:otel:stage-events");var HTTP_SPAN_CTX_KEY=Symbol.for("frontmcp:otel:http-span-ctx");function sessionTracingId(sessionId){return sha256Hex(sessionId).slice(0,16)}function getTracer(){return trace3.getTracer("@frontmcp/observability")}function extractContext(flowCtx){try{const ctx=flowCtx.get?.(Symbol.for("frontmcp:CONTEXT"));if(ctx)return ctx}catch{}return flowCtx.state?.ctx??flowCtx.state?.frontmcpContext}function storeActiveSpan(flowCtx,span,otelCtx){try{const ctx=flowCtx.get?.(Symbol.for("frontmcp:CONTEXT"));if(ctx&&typeof ctx.set==="function"){ctx.set(ACTIVE_SPAN_KEY,span);ctx.set(ACTIVE_OTEL_CTX_KEY,otelCtx)}}catch{}}function clearActiveSpan(flowCtx){try{const ctx=flowCtx.get?.(Symbol.for("frontmcp:CONTEXT"));if(ctx&&typeof ctx.delete==="function"){ctx.delete(ACTIVE_SPAN_KEY);ctx.delete(ACTIVE_OTEL_CTX_KEY)}}catch{}}function beginFlowSpan(flowCtx,options,span,spanCtx){flowCtx.state[SPAN_KEY]=span;flowCtx.state[SPAN_CTX_KEY]=spanCtx;flowCtx.state[STAGE_TS_KEY]=Date.now();flowCtx.state[STAGE_EVENTS_KEY]=options.flowStageEvents!==false}function parentContextOf(ctx){return ctx.get?.(HTTP_SPAN_CTX_KEY)??createOTelContextFromTrace(ctx.traceContext)}function flowFailureOf(flowError){const failed=flowError?.originalError;const error=flowError instanceof FlowControl?failed instanceof Error?failed:new InternalMcpError(`Flow ended with: ${flowError.type}`):flowError instanceof Error?flowError:new Error(String(flowError));const reported=toMcpError(error);return{error,type:reported.name,message:reported.getPublicMessage(),code:reported.code,errorId:reported.errorId}}function endFailedSpan(span,flowError){const failure=flowFailureOf(flowError);span.setStatus({code:SpanStatusCode2.ERROR,message:failure.message});span.recordException({name:failure.type,message:failure.message,code:failure.code,stack:failure.error.stack});span.end()}function traceparentOf(span){const{traceId,spanId,traceFlags}=span.spanContext();return`00-${traceId}-${spanId}-${traceFlags.toString(16).padStart(2,"0")}`}function recordStageEvent(span,stageName,state){if(state[STAGE_EVENTS_KEY]===false)return;const now=Date.now();const prev=state[STAGE_TS_KEY];const attributes={};if(prev){attributes["duration_ms"]=now-prev}state[STAGE_TS_KEY]=now;span.addEvent(`stage.${stageName}`,attributes)}function onHttpWillTrace(options,flowCtx){if(options.httpSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=createOTelContextFromTrace(ctx.traceContext);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startHttpServerSpan(tracer,{method:ctx.metadata?.customHeaders?.["x-http-method"]??"POST",path:ctx.metadata?.customHeaders?.["x-url-path"]??"/",scopeId:ctx.scopeId,requestId:ctx.requestId,parentContext:parentOTelCtx});span.setAttribute(McpAttributes.SESSION_ID,sessionHash);span.setAttribute(FrontMcpAttributes.SESSION_ID_HASH,sessionHash);ctx.set?.(HTTP_SPAN_CTX_KEY,spanCtx);beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"traceRequest",flowCtx.state)}function onHttpWillAcquireQuota(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"acquireQuota",flowCtx.state)}function onHttpDidAcquireQuota(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"acquireQuota.done",flowCtx.state)}function onHttpWillCheckAuth(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"checkAuthorization",flowCtx.state)}function onHttpDidCheckAuth(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"checkAuthorization.done",flowCtx.state)}function onHttpWillRoute(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"router",flowCtx.state)}function onHttpDidRoute(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"router.done",flowCtx.state)}function onHttpDidFinalize(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"finalize",flowCtx.state);const statusCode=flowCtx.state?.statusCode??200;setHttpResponseStatus(span,statusCode);if(statusCode>=400){endSpanError(span,`HTTP ${statusCode}`)}else{endSpanOk(span)}}function onToolWillParse(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startRpcSpan(tracer,{method:"tools/call",scopeId:ctx.scopeId,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onToolWillFindTool(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"findTool",flowCtx.state)}function onToolWillCheckAuth(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"checkToolAuthorization",flowCtx.state)}function onEntryWillCheckAuthorities(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"checkEntryAuthorities",flowCtx.state)}function onEntryDidCheckAuthorities(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"checkEntryAuthorities.done",flowCtx.state);span.setAttribute("auth.authorities.result","granted")}function onToolWillCreateContext(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"createToolCallContext",flowCtx.state)}function onToolWillValidateInput(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"validateInput",flowCtx.state)}function onToolWillExecute(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);const rpcCtx=flowCtx.state?.[SPAN_CTX_KEY];const tracer=getTracer();const toolName=flowCtx.state?.input?.name??"unknown";const toolOwner=flowCtx.state?._toolOwnerId;const enduser=ctx?.authInfo;const{span:toolSpan,context:toolOTelCtx}=startToolSpan(tracer,{name:toolName,owner:toolOwner,enduserId:enduser?.clientId??enduser?.extra?.sub,enduserScope:Array.isArray(enduser?.scopes)?enduser.scopes.join(" "):void 0,parentContext:rpcCtx});flowCtx.state[EXEC_SPAN_KEY]=toolSpan;flowCtx.state[STAGE_TS_KEY]=Date.now();recordStageEvent(toolSpan,"execute.start",flowCtx.state);storeActiveSpan(flowCtx,toolSpan,toolOTelCtx)}function onToolDidExecute(options,flowCtx){const toolSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!toolSpan)return;recordStageEvent(toolSpan,"execute.done",flowCtx.state);endSpanOk(toolSpan);flowCtx.state[EXEC_SPAN_KEY]=void 0;clearActiveSpan(flowCtx)}function onToolWillValidateOutput(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"validateOutput",flowCtx.state)}function onToolWillApplyUI(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"applyUI",flowCtx.state)}function onToolDidFinalize(flowCtx){const rpcSpan=flowCtx.state?.[SPAN_KEY];const toolSpan=flowCtx.state?.[EXEC_SPAN_KEY];const error=flowCtx.state?.flowError;if(error){if(toolSpan)endFailedSpan(toolSpan,error);if(rpcSpan)endFailedSpan(rpcSpan,error)}else if(rpcSpan){recordStageEvent(rpcSpan,"finalize",flowCtx.state);endSpanOk(rpcSpan)}}function onResourceWillParse(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startRpcSpan(tracer,{method:"resources/read",scopeId:ctx.scopeId,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onResourceWillFind(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"findResource",flowCtx.state)}function onResourceWillExecute(options,flowCtx){if(options.executionSpans===false)return;const rpcCtx=flowCtx.state?.[SPAN_CTX_KEY];const tracer=getTracer();const uri=flowCtx.state?.input?.uri??"unknown";const{span:resSpan,context:resOTelCtx}=startResourceSpan(tracer,{uri,parentContext:rpcCtx});flowCtx.state[EXEC_SPAN_KEY]=resSpan;flowCtx.state[STAGE_TS_KEY]=Date.now();recordStageEvent(resSpan,"execute.start",flowCtx.state);storeActiveSpan(flowCtx,resSpan,resOTelCtx)}function onResourceDidExecute(flowCtx){const resSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!resSpan)return;recordStageEvent(resSpan,"execute.done",flowCtx.state);endSpanOk(resSpan);flowCtx.state[EXEC_SPAN_KEY]=void 0;clearActiveSpan(flowCtx)}function onResourceDidFinalize(flowCtx){const rpcSpan=flowCtx.state?.[SPAN_KEY];const resSpan=flowCtx.state?.[EXEC_SPAN_KEY];const error=flowCtx.state?.flowError;if(error){if(resSpan)endFailedSpan(resSpan,error);if(rpcSpan)endFailedSpan(rpcSpan,error)}else if(rpcSpan){recordStageEvent(rpcSpan,"finalize",flowCtx.state);endSpanOk(rpcSpan)}}function onPromptWillParse(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startRpcSpan(tracer,{method:"prompts/get",scopeId:ctx.scopeId,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onPromptWillFind(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"findPrompt",flowCtx.state)}function onPromptWillExecute(options,flowCtx){if(options.executionSpans===false)return;const rpcCtx=flowCtx.state?.[SPAN_CTX_KEY];const tracer=getTracer();const promptName=flowCtx.state?.input?.name??"unknown";const{span:promptSpan,context:promptOTelCtx}=startPromptSpan(tracer,{name:promptName,parentContext:rpcCtx});flowCtx.state[EXEC_SPAN_KEY]=promptSpan;flowCtx.state[STAGE_TS_KEY]=Date.now();recordStageEvent(promptSpan,"execute.start",flowCtx.state);storeActiveSpan(flowCtx,promptSpan,promptOTelCtx)}function onPromptDidExecute(flowCtx){const promptSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!promptSpan)return;recordStageEvent(promptSpan,"execute.done",flowCtx.state);endSpanOk(promptSpan);flowCtx.state[EXEC_SPAN_KEY]=void 0;clearActiveSpan(flowCtx)}function onPromptDidFinalize(flowCtx){const rpcSpan=flowCtx.state?.[SPAN_KEY];const promptSpan=flowCtx.state?.[EXEC_SPAN_KEY];const error=flowCtx.state?.flowError;if(error){if(promptSpan)endFailedSpan(promptSpan,error);if(rpcSpan)endFailedSpan(rpcSpan,error)}else if(rpcSpan){recordStageEvent(rpcSpan,"finalize",flowCtx.state);endSpanOk(rpcSpan)}}function onAgentWillParse(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startRpcSpan(tracer,{method:"agents/call",scopeId:ctx.scopeId,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onAgentWillFind(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"findAgent",flowCtx.state)}function onAgentWillExecute(options,flowCtx){if(options.executionSpans===false)return;const rpcCtx=flowCtx.state?.[SPAN_CTX_KEY];const tracer=getTracer();const agentName=flowCtx.state?.input?.name??"unknown";const{span:agentSpan}=startSpan(tracer,{name:`agent ${agentName}`,kind:SpanKind12.INTERNAL,attributes:{[FrontMcpAttributes.FLOW_NAME]:"agents:call-agent",[McpAttributes.COMPONENT_TYPE]:"agent",[McpAttributes.COMPONENT_KEY]:`agent:${agentName}`},parentContext:rpcCtx});const agentOTelCtx=trace3.setSpan(rpcCtx??otelContext3.active(),agentSpan);flowCtx.state[EXEC_SPAN_KEY]=agentSpan;flowCtx.state[STAGE_TS_KEY]=Date.now();recordStageEvent(agentSpan,"execute.start",flowCtx.state);storeActiveSpan(flowCtx,agentSpan,agentOTelCtx)}function onAgentDidExecute(flowCtx){const agentSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!agentSpan)return;recordStageEvent(agentSpan,"execute.done",flowCtx.state);endSpanOk(agentSpan);flowCtx.state[EXEC_SPAN_KEY]=void 0;clearActiveSpan(flowCtx)}function onAgentDidFinalize(flowCtx){const rpcSpan=flowCtx.state?.[SPAN_KEY];const agentSpan=flowCtx.state?.[EXEC_SPAN_KEY];const error=flowCtx.state?.flowError;if(error){if(agentSpan)endFailedSpan(agentSpan,error);if(rpcSpan)endFailedSpan(rpcSpan,error)}else if(rpcSpan){recordStageEvent(rpcSpan,"finalize",flowCtx.state);endSpanOk(rpcSpan)}}function onGenericFlowWillStart(flowName,options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startSpan(tracer,{name:flowName,kind:SpanKind12.INTERNAL,attributes:{[FrontMcpAttributes.FLOW_NAME]:flowName,[McpAttributes.SESSION_ID]:sessionHash,[FrontMcpAttributes.SESSION_ID_HASH]:sessionHash,[FrontMcpAttributes.SCOPE_ID]:ctx.scopeId,[FrontMcpAttributes.REQUEST_ID]:ctx.requestId},parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx)}function onGenericFlowStage(stageName,flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,stageName,flowCtx.state)}function onGenericFlowDidFinalize(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;const error=flowCtx.state?.flowError;if(error){endFailedSpan(span,error)}else{endSpanOk(span)}}function onTransportWillStart(transportType,options,flowCtx){if(options.transportSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startTransportSpan(tracer,{type:transportType,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onTransportDidRoute(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"router",flowCtx.state);const requestType=flowCtx.state?.requestType;if(requestType)setTransportRequestType(span,requestType)}function onTransportStage(stageName,flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,stageName,flowCtx.state)}function onTransportDidFinalize(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"cleanup",flowCtx.state);const error=flowCtx.state?.flowError;if(error){endFailedSpan(span,error)}else{endSpanOk(span)}}function onAuthWillStart(flowName,options,flowCtx){if(options.authSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const{span,context:spanCtx}=startAuthSpan(tracer,{flowName,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onAuthDidDetermineMode(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"determineAuthMode",flowCtx.state);const mode=flowCtx.state?.authMode;if(mode)setAuthMode(span,mode)}function onAuthStage(stageName,flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,stageName,flowCtx.state)}function onAuthDidFinalize(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;const error=flowCtx.state?.flowError;if(error){setAuthResult(span,"unauthorized");endFailedSpan(span,error)}else{setAuthResult(span,"authorized");endSpanOk(span)}}function wrapContextFetch(options,flowCtx){const toolCtx=flowCtx.state?.toolContext??flowCtx.state?.toolCallContext;if(!toolCtx||typeof toolCtx.fetch!=="function")return;const originalFetch=toolCtx.fetch.bind(toolCtx);const parentOTelCtx=flowCtx.state?.[SPAN_CTX_KEY];toolCtx.fetch=async(input,init)=>{const fetchSpan=options.fetchSpans===false?void 0:startFetchSpan(getTracer(),{method:init?.method??(input instanceof Request?input.method:"GET"),url:typeof input==="string"?input:input instanceof URL?input.toString():input.url,parentContext:parentOTelCtx}).span;const callingSpan=fetchSpan??flowCtx.state?.[EXEC_SPAN_KEY]??flowCtx.state?.[SPAN_KEY];const headers=new Headers(init?.headers??(input instanceof Request?input.headers:void 0));if(callingSpan&&!headers.has("traceparent"))headers.set("traceparent",traceparentOf(callingSpan));try{const response=await originalFetch(input,{...init,headers});if(fetchSpan){setFetchResponseStatus(fetchSpan,response.status);endSpanOk(fetchSpan)}return response}catch(err){if(fetchSpan)endSpanError(fetchSpan,err instanceof Error?err:String(err));throw err}}}function onAgentDidExecuteEnrich(flowCtx){const agentSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!agentSpan)return;const meta=flowCtx.state?.executionMeta;if(meta){if(typeof meta.iterations==="number"){agentSpan.setAttribute(FrontMcpAttributes.AGENT_ITERATIONS,meta.iterations)}if(typeof meta.durationMs==="number"){agentSpan.setAttribute(FrontMcpAttributes.AGENT_EXECUTION_DURATION_MS,meta.durationMs)}}}var OBSERVED_KEY=Symbol.for("frontmcp:observability:hook-observer");function installHookObserver(flowCtx,observer){const ctx=extractContext(flowCtx);if(!ctx?.get||!ctx.set||ctx.get(OBSERVED_KEY))return;ctx.set(OBSERVED_KEY,true);addHookObserver({get:key=>ctx.get?.(key),set:(key,value)=>ctx.set?.(key,value)},observer)}async function runInHookSpan(flowCtx,hook,run){const ctx=extractContext(flowCtx);const{span}=startHookSpan(getTracer(),{...hook,parentContext:flowCtx.state?.[SPAN_CTX_KEY]??(ctx&&parentContextOf(ctx))});try{await run();endSpanOk(span)}catch(error){if(error instanceof FlowControl&&error.type!=="fail"&&error.type!=="abort")endSpanOk(span);else endFailedSpan(span,error);throw error}}function reportStartup(data){const tracer=getTracer();emitStartupReport(tracer,data)}var REQUEST_LOG_COLLECTOR=Symbol.for("frontmcp:observability:request-log-collector");var FRONTMCP_CONTEXT=Symbol.for("frontmcp:CONTEXT");function resolve(flowCtx,token){try{return flowCtx.get?.(token)}catch{return void 0}}function currentRequestLog(flowCtx){return resolve(flowCtx,FRONTMCP_CONTEXT)?.get(REQUEST_LOG_COLLECTOR)}function startRequestLog(flowCtx,options){const context=resolve(flowCtx,FRONTMCP_CONTEXT);if(!context)return;const collector=new RequestLogCollector({requestId:context.requestId,traceId:context.traceContext.traceId,sessionIdHash:sessionTracingId(context.sessionId).slice(0,12),scopeId:context.scopeId},options);context.set(REQUEST_LOG_COLLECTOR,collector);const request=flowCtx.rawInput?.request;if(request?.method&&request.path)collector.setHttpInfo(request.method,request.path);const rpcMethod=request?.body?.method;if(typeof rpcMethod==="string")collector.setRpcMethod(rpcMethod)}function recordRequestLogFailure(flowCtx){const flowError=flowCtx.state?.["flowError"];if(!flowError)return;const{type,message,code,errorId}=flowFailureOf(flowError);currentRequestLog(flowCtx)?.setError({type,message,code,error_id:errorId})}function recordRequestLogAuth(flowCtx){const verifyResult=flowCtx.state?.["verifyResult"];const authorization=flowCtx.rawInput?.request?.headers?.["authorization"];const scheme=typeof authorization==="string"?authorization.trim().split(/\s+/)[0].toLowerCase():"";const sub=verifyResult?.authorization?.user?.sub;const anonymous=typeof sub!=="string"||isAnonymousSubject(sub);currentRequestLog(flowCtx)?.setAuthInfo(anonymous||!scheme?"anonymous":scheme,verifyResult?.kind==="authorized"&&!anonymous)}async function completeRequestLog(flowCtx){const collector=currentRequestLog(flowCtx);if(!collector||collector.isFinalized())return;const statusCode=flowCtx.state?.["statusCode"]??flowCtx.rawInput?.response?.statusCode;if(typeof statusCode==="number")collector.setStatusCode(statusCode);await collector.finalize()}import{FlowHooksOf,ResourceHook,ToolHook}from"@frontmcp/sdk";import{appendFile,dirname,ensureDir}from"@frontmcp/utils";var DEV_EVENTS_IPC_MESSAGE="dev-events";var JsonlFileSink=class{constructor(path){this.path=path;this.name="file"}async write(events){this.folderReady??=ensureDir(dirname(this.path));await this.folderReady;await appendFile(this.path,events.map(event=>`${JSON.stringify(event)}
5
- `).join(""))}};var IpcDevEventSink=class{constructor(){this.name="ipc"}write(events){const send=process.send;if(typeof send!=="function"||!process.connected)throw new Error("no IPC channel to the dev parent");return new Promise((resolve2,reject)=>{send.call(process,{__frontmcp:DEV_EVENTS_IPC_MESSAGE,events},error=>error?reject(error):resolve2())})}};var DevEventStream=class{constructor(sinks,options){this.sinks=sinks;this.options=options;this.queue=[];this.closed=false;this.warnedFull=false;this.failedSinks=new Set}emit(event){if(this.closed)return;if(this.queue.length>=this.options.maxQueue){if(!this.warnedFull){this.warnedFull=true;this.options.logger.warn(`Dev events: the queue of ${this.options.maxQueue} events is full; new events are dropped until the sinks catch up`)}return}this.queue.push(event);this.draining??=this.drain()}flush(){return this.draining??Promise.resolve()}async onShutdown(){while(this.draining)await this.draining;this.closed=true;await Promise.all(this.sinks.map(sink=>this.attempt(sink,()=>sink.close?.())))}async drain(){await Promise.resolve();while(this.queue.length>0){const batch=this.queue;this.queue=[];await Promise.all(this.sinks.map(sink=>this.attempt(sink,()=>sink.write(batch))))}this.draining=void 0}async attempt(sink,run){try{await run()}catch(error){if(this.failedSinks.has(sink))return;this.failedSinks.add(sink);const reason=error instanceof Error?error.message:String(error);this.options.logger.warn(`Dev events: the ${sink.name??"custom"} sink failed (${reason}); its later failures are not logged`)}}};import{metrics}from"@opentelemetry/api";function snapshotKey(name,attributes){const keys=Object.keys(attributes).sort();if(keys.length===0)return name;const tail=keys.map(k=>`${k}=${attributes[k]}`).join(",");return`${name}{${tail}}`}var snapshotStore=new Map;var TelemetryCounterImpl=class{constructor(name,otelCounter){this.name=name;this.otelCounter=otelCounter}inc(by=1,attributes={}){if(!Number.isFinite(by)||by<0){return}try{this.otelCounter.add(by,attributes)}catch{}const key=snapshotKey(this.name,attributes);const existing=snapshotStore.get(key);if(existing){existing.count+=by}else{snapshotStore.set(key,{name:this.name,count:by,attributes:{...attributes}})}}};var METER_NAME="@frontmcp/observability";var counterCache=new Map;function createCounter(name,description){const existing=counterCache.get(name);if(existing)return existing;const meter=metrics.getMeter(METER_NAME);const otelCounter=meter.createCounter(name,description?{description}:void 0);const counter=new TelemetryCounterImpl(name,otelCounter);counterCache.set(name,counter);return counter}function getMetricSnapshot(){return Array.from(snapshotStore.values()).map(entry=>({name:entry.name,count:entry.count,attributes:{...entry.attributes}}))}function getCounterTotal(name){let sum=0;for(const entry of snapshotStore.values()){if(entry.name===name)sum+=entry.count}return sum}function resetMetricSnapshot(){snapshotStore.clear()}function resetTelemetrySnapshotForTesting(){snapshotStore.clear()}function resetCounterCacheForTesting(){counterCache.clear()}var KNOWN_BUNDLE_SOURCES=["static","npm","saas-pull","webhook","filesystem","unknown"];function normalizeBundleSource(value){if(typeof value!=="string")return"unknown";return KNOWN_BUNDLE_SOURCES.includes(value)?value:"unknown"}var KNOWN_ERROR_REASONS=["network","timeout","invalid_response","parse_error","unknown"];function normalizeErrorReason(err){if(!err)return"unknown";const name=err instanceof Error?err.name:"";const message=err instanceof Error?err.message:typeof err==="string"?err:"";const haystack=`${name} ${message}`.toLowerCase();if(name==="TimeoutError"||haystack.includes("timeout")||haystack.includes("timed out")){return"timeout"}if(name==="NetworkError"||name==="FetchError"||haystack.includes("network")||haystack.includes("econnrefused")||haystack.includes("econnreset")||haystack.includes("enotfound")||haystack.includes("socket")||haystack.includes("dns")){return"network"}if(name==="SyntaxError"||haystack.includes("parse")||haystack.includes("json")){return"parse_error"}if(name==="TypeError"||name==="RangeError"||haystack.includes("invalid")||haystack.includes("malformed")||haystack.includes("schema")){return"invalid_response"}return"unknown"}var InFlightCalls=class{constructor(now){this.now=now;this.records=new Set}async track(call,body,stillRunning=()=>void 0){const record={...call,startedAt:this.now()};this.records.add(record);const end=()=>{record.endedAt??=this.now()};try{await body()}finally{const execution=stillRunning();if(execution instanceof Promise)execution.then(end,end);else end()}}running(){return[...this.records].filter(record=>record.endedAt===void 0).map(record=>({...record}))}during(from,to){return[...this.records].filter(record=>record.startedAt<=to&&(record.endedAt??to)>=from).map(record=>({...record}))}prune(time){for(const record of this.records){if(record.endedAt!==void 0&&record.endedAt<time)this.records.delete(record)}}};var SAMPLE_INTERVAL_MS=10;function observeGcPauses(record){let perfHooks;try{perfHooks=__require("node:perf_hooks")}catch{return void 0}try{const observer=new perfHooks.PerformanceObserver(list=>{for(const entry of list.getEntries())record({startTime:entry.startTime,duration:entry.duration})});observer.observe({entryTypes:["gc"]});return()=>observer.disconnect()}catch{return()=>void 0}}function overlapMs(pause,stall){return Math.max(0,Math.min(pause.startTime+pause.duration,stall.to)-Math.max(pause.startTime,stall.from))}var StallDetector=class{constructor(options){this.pending=[];this.gcPauses=[];this.previousSampleAt=0;this.thresholdMs=options.thresholdMs;this.onStall=options.onStall;this.now=options.now??(()=>performance.now());this.observeGc=options.observeGc??observeGcPauses;this.calls=new InFlightCalls(this.now)}get running(){return this.timer!==void 0}start(){if(this.timer)return;this.stopObservingGc=this.observeGc(pause=>this.gcPauses.push(pause));if(!this.stopObservingGc)return;this.previousSampleAt=this.now();this.timer=setInterval(()=>this.sample(),SAMPLE_INTERVAL_MS);this.timer.unref?.()}stop(){clearInterval(this.timer);this.timer=void 0;this.reportPending();this.stopObservingGc?.();this.stopObservingGc=void 0}sample(){if(!this.timer)return;const now=this.now();this.reportPending();const from=this.previousSampleAt;const stallMs=now-from;if(stallMs>=this.thresholdMs)this.pending.push({from,to:now,stallMs,calls:this.calls.during(from,now)});this.calls.prune(now);const keepFrom=Math.min(now,...this.pending.map(stall=>stall.from));this.gcPauses=this.gcPauses.filter(pause=>pause.startTime+pause.duration>=keepFrom);this.previousSampleAt=now}reportPending(){for(const stall of this.pending.splice(0)){try{this.onStall(this.reportOf(stall))}catch{}}}reportOf(stall){const gcTotal=this.gcPauses.reduce((sum,pause)=>sum+overlapMs(pause,stall),0);const gcMs=Math.min(stall.stallMs,gcTotal);const cause=stall.stallMs-gcMs<this.thresholdMs?"gc":stall.calls.length>0?"calls":"unknown";return{stallMs:Math.round(stall.stallMs),gcMs:Math.round(gcMs),cause,calls:stall.calls.map(({method,entry,session,startedAt,endedAt})=>({method,entry,...session?{session}:{},runningMs:Math.round(Math.min(endedAt??stall.to,stall.to)-startedAt)}))}}};var STALL_SECONDS_COUNTER="frontmcp_event_loop_stall_seconds_total";var STALL_SECONDS_DESCRIPTION="Seconds the event loop was stalled, by the method and entry of each call in flight, or gc, or unknown";var MAX_NAMED_CALLS=5;function describeCall(call){const session=call.session?`, session ${call.session}`:"";return`${call.method} ${call.entry} (${call.runningMs} ms${session})`}function describeStall(report){const head=`Event loop stalled for ${report.stallMs} ms`;if(report.cause==="gc")return`${head}, ${report.gcMs} ms of it in garbage collection`;const gc=report.gcMs>0?` (${report.gcMs} ms in garbage collection)`:"";if(report.calls.length===0)return`${head}${gc} with no call in flight`;const named=report.calls.slice(0,MAX_NAMED_CALLS).map(describeCall).join(", ");const more=report.calls.length>MAX_NAMED_CALLS?` and ${report.calls.length-MAX_NAMED_CALLS} more`:"";return`${head}${gc} while running ${named}${more}`}function countStall(report,counter){if(report.gcMs>0)counter.inc(report.gcMs/1e3,{cause:"gc",entry:""});if(report.cause==="gc")return;const seconds=(report.stallMs-report.gcMs)/1e3;if(report.calls.length===0){counter.inc(seconds,{cause:"unknown",entry:""});return}const entries=new Map(report.calls.map(call=>[`${call.method} ${call.entry}`,call]));for(const call of entries.values())counter.inc(seconds,{cause:call.method,entry:call.entry})}var PromptHook=FlowHooksOf("prompts:get-prompt");function resolvedEntryOf(flow,method){if(method==="tools/call")return flow.state?.tool?.fullName;if(method==="resources/read")return flow.state?.resource?.fullName;return flow.state?.prompt?.fullName}function reportedEntryOf(flow,method){const requested=method==="tools/call"?flow.toolName:method==="prompts/get"?flow.promptName:void 0;return resolvedEntryOf(flow,method)??requested??""}function sessionOf(flow){const sessionId=flow.request?.sessionId;return sessionId?{session:sessionTracingId(sessionId).slice(0,12)}:{}}function sinksOf(options){return[...options.file?[new JsonlFileSink(options.file)]:[],...options.ipc?[new IpcDevEventSink]:[],...options.sinks]}var _CallMonitor=class _CallMonitor{constructor(stallOptions,devEventsOptions,logger){this.logger=logger;this.callStarts=new WeakMap;this.devEvents=devEventsOptions?new DevEventStream(sinksOf(devEventsOptions),{maxQueue:devEventsOptions.maxQueue,logger}):void 0;if(!stallOptions)return;this.stallCounter=createCounter(STALL_SECONDS_COUNTER,STALL_SECONDS_DESCRIPTION);this.sharedStalls=_CallMonitor.sharedDetectorFor(stallOptions.thresholdMs);this.stalls=this.sharedStalls.detector}static{this.sharedDetectors=new Map}static sharedDetectorFor(thresholdMs){const existing=_CallMonitor.sharedDetectors.get(thresholdMs);if(existing)return existing;const monitors=new Set;const detector=new StallDetector({thresholdMs,onStall:report=>{const[reporter]=monitors;reporter?.reportStall(report)}});const shared={detector,monitors};_CallMonitor.sharedDetectors.set(thresholdMs,shared);return shared}onReady(){if(!this.sharedStalls)return;this.sharedStalls.monitors.add(this);this.sharedStalls.detector.start()}async onShutdown(){const shared=this.sharedStalls;if(shared?.monitors.has(this)){if(shared.monitors.size===1)shared.detector.stop();shared.monitors.delete(this)}await this.devEvents?.onShutdown()}markToolCallStart(ctx){this.markStart(ctx)}trackToolExecution(ctx,next){return this.track(ctx,"tools/call",next)}reportToolCall(ctx){this.report(ctx,"tools/call")}markResourceReadStart(ctx){this.markStart(ctx)}trackResourceExecution(ctx,next){return this.track(ctx,"resources/read",next)}reportResourceRead(ctx){this.report(ctx,"resources/read")}markPromptGetStart(ctx){this.markStart(ctx)}trackPromptExecution(ctx,next){return this.track(ctx,"prompts/get",next)}reportPromptGet(ctx){this.report(ctx,"prompts/get")}markStart(ctx){if(this.devEvents&&typeof ctx==="object"&&ctx!==null)this.callStarts.set(ctx,performance.now())}track(ctx,method,next){const flow=ctx;const entry=resolvedEntryOf(flow,method);if(!this.stalls?.running||!entry)return next();return this.stalls.calls.track({method,entry,...sessionOf(flow)},next,()=>flow.state?.abandonedExecution)}reportStall(report){this.logger.warn(describeStall(report));if(this.stallCounter)countStall(report,this.stallCounter);this.devEvents?.emit({type:"stall",at:new Date().toISOString(),...report})}report(ctx,method){if(!this.devEvents||typeof ctx!=="object"||ctx===null)return;const startedAt=this.callStarts.get(ctx);if(startedAt===void 0)return;const flow=ctx;const failure=flow.state?.flowError?flowFailureOf(flow.state.flowError):void 0;this.devEvents.emit({type:"call",at:new Date().toISOString(),method,entry:reportedEntryOf(flow,method),durationMs:Math.round((performance.now()-startedAt)*10)/10,outcome:failure?"error":"ok",...failure?{error:{type:failure.type,code:failure.code}}:{},...sessionOf(flow)})}};__decorateClass([ToolHook.Will("parseInput",{priority:-1e3})],_CallMonitor.prototype,"markToolCallStart",1);__decorateClass([ToolHook.Around("execute",{priority:-1e3})],_CallMonitor.prototype,"trackToolExecution",1);__decorateClass([ToolHook.Finally("finalize",{priority:1e3})],_CallMonitor.prototype,"reportToolCall",1);__decorateClass([ResourceHook.Will("parseInput",{priority:-1e3})],_CallMonitor.prototype,"markResourceReadStart",1);__decorateClass([ResourceHook.Around("execute",{priority:-1e3})],_CallMonitor.prototype,"trackResourceExecution",1);__decorateClass([ResourceHook.Finally("finalize",{priority:1e3})],_CallMonitor.prototype,"reportResourceRead",1);__decorateClass([PromptHook.Will("parseInput",{priority:-1e3})],_CallMonitor.prototype,"markPromptGetStart",1);__decorateClass([PromptHook.Around("execute",{priority:-1e3})],_CallMonitor.prototype,"trackPromptExecution",1);__decorateClass([PromptHook.Finally("finalize",{priority:1e3})],_CallMonitor.prototype,"reportPromptGet",1);var CallMonitor=_CallMonitor;import{SpanKind as SpanKind13,SpanStatusCode as SpanStatusCode3,trace as trace4}from"@opentelemetry/api";var TelemetrySpan=class{constructor(span){this.span=span;this.hasError=false}setAttribute(key,value){this.span.setAttribute(key,value);return this}setAttributes(attrs){this.span.setAttributes(attrs);return this}addEvent(name,attributes){this.span.addEvent(name,attributes);return this}recordError(error){this.span.recordException(error);this.span.setStatus({code:SpanStatusCode3.ERROR,message:error.message});this.hasError=true;return this}end(){if(!this.hasError){this.span.setStatus({code:SpanStatusCode3.OK})}this.span.end()}endWithError(error){const msg=typeof error==="string"?error:error.message;if(error instanceof Error)this.span.recordException(error);this.span.setStatus({code:SpanStatusCode3.ERROR,message:msg});this.span.end()}get raw(){return this.span}};var TelemetryAccessor=class{constructor(ctx){this.ctx=ctx;this.tracer=trace4.getTracer("@frontmcp/observability");this.fallbackContext=createOTelContextFromTrace(ctx.traceContext);this.sessionHash=sessionTracingId(ctx.sessionId);this.baseAttributes={[FrontMcpAttributes.REQUEST_ID]:ctx.requestId,[FrontMcpAttributes.SCOPE_ID]:ctx.scopeId,[McpAttributes.SESSION_ID]:this.sessionHash}}getActiveContext(){const otelCtx=this.ctx.get?.(ACTIVE_OTEL_CTX_KEY);return otelCtx??this.fallbackContext}getActiveSpan(){return this.ctx.get?.(ACTIVE_SPAN_KEY)}startSpan(name,attributes){const span=this.tracer.startSpan(name,{kind:SpanKind13.INTERNAL,attributes:{...this.baseAttributes,...attributes}},this.getActiveContext());return new TelemetrySpan(span)}async withSpan(name,fn,attributes){const telemetrySpan=this.startSpan(name,attributes);try{const result=await fn(telemetrySpan);telemetrySpan.end();return result}catch(err){telemetrySpan.endWithError(err instanceof Error?err:String(err));throw err}}addEvent(name,attributes){const activeSpan=this.getActiveSpan();if(activeSpan){activeSpan.addEvent(name,attributes)}else{const span=this.tracer.startSpan(name,{kind:SpanKind13.INTERNAL,attributes:this.baseAttributes},this.fallbackContext);if(attributes)span.addEvent(name,attributes);span.setStatus({code:SpanStatusCode3.OK});span.end()}}setAttributes(attrs){const activeSpan=this.getActiveSpan();if(activeSpan){activeSpan.setAttributes(attrs)}}createCounter(name,description){return createCounter(name,description)}get traceId(){return trace4.getSpan(this.fallbackContext)?.spanContext().traceId??""}get sessionId(){return this.sessionHash}};import{SpanStatusCode as SpanStatusCode4,trace as trace5}from"@opentelemetry/api";var TelemetryFactory=class{constructor(tracerName="@frontmcp/observability"){this.tracer=trace5.getTracer(tracerName)}createCounter(name,description){return createCounter(name,description)}startSpan(name,attributes,parent){const opts=attributes?{attributes}:void 0;const span=parent?this.tracer.startSpan(name,opts,parent):this.tracer.startSpan(name,opts);return new TelemetrySpan(span)}async withSpan(name,fn,attributes){const span=this.startSpan(name,attributes);try{const result=await fn(span);span.end();return result}catch(err){span.endWithError(err instanceof Error?err:String(err));throw err}}};var TELEMETRY_ACCESSOR=Symbol.for("frontmcp:observability:telemetry-accessor");var TELEMETRY_FACTORY=Symbol.for("frontmcp:observability:telemetry-factory");import{z}from"@frontmcp/sdk";import{InternalMcpError as InternalMcpError2}from"@frontmcp/sdk";var ObservabilityConfigurationError=class extends InternalMcpError2{constructor(message){super(message,"OBSERVABILITY_CONFIGURATION");this.name="ObservabilityConfigurationError"}};var DEV_EVENTS_FILE_ENV="FRONTMCP_DEV_EVENTS_FILE";var DEV_EVENTS_IPC_ENV="FRONTMCP_DEV_EVENTS_IPC";var thresholdMessage={message:"must be a whole number of milliseconds from 20 to 60000"};var maxQueueMessage={message:"must be a whole number from 1 to 100000"};var stallOptionsSchema=z.object({thresholdMs:z.number().int(thresholdMessage).min(20,thresholdMessage).max(6e4,thresholdMessage).default(200)}).strict();var isSink=value=>typeof value==="object"&&value!==null&&typeof value.write==="function";var devEventsOptionsSchema=z.object({file:z.string().min(1,{message:"must be a file path"}).optional(),sinks:z.array(z.custom(isSink,{message:"must be a sink: an object with a write(events) method"})).default([]),maxQueue:z.number().int(maxQueueMessage).min(1,maxQueueMessage).max(1e5,maxQueueMessage).default(1e3)}).strict();function parse(option,schema,input){const result=schema.safeParse(input);if(result.success)return result.data;const problems=result.error.issues.map(issue=>`${[option,...issue.path].join(".")}: ${issue.message}`);throw new ObservabilityConfigurationError(`Invalid ObservabilityPlugin options: ${problems.join("; ")}`)}function resolveStallOptions(input){if(input===void 0||input===false)return false;return parse("stalls",stallOptionsSchema,input===true?{}:input)}function resolveDevEventsOptions(input,env=process.env){if(input===false)return false;const options=parse("devEvents",devEventsOptionsSchema,input===true||input===void 0?{}:input);const envFile=env[DEV_EVENTS_FILE_ENV]||void 0;const ipc=env[DEV_EVENTS_IPC_ENV]==="1";const inDevelopment=envFile!==void 0||ipc||env["NODE_ENV"]==="development";const file=options.file??envFile;if(!inDevelopment||!file&&!ipc&&options.sinks.length===0)return false;return{...file?{file}:{},ipc,sinks:options.sinks,maxQueue:options.maxQueue}}var PromptHook2=FlowHooksOf2("prompts:get-prompt");var ListPromptsHook=FlowHooksOf2("prompts:list-prompts");var SkillSearchHook=FlowHooksOf2("skills:search");var SkillLoadHook=FlowHooksOf2("skills:load");var CompletionHook=FlowHooksOf2("completion:complete");var LegacySseHook=FlowHooksOf2("handle:legacy-sse");var StreamableHttpHook=FlowHooksOf2("handle:streamable-http");var StatelessHttpHook=FlowHooksOf2("handle:stateless-http");var AuthVerifyHook=FlowHooksOf2("auth:verify");var SessionVerifyHook=FlowHooksOf2("session:verify");var OAuthTokenHook=FlowHooksOf2("oauth:token");var OAuthAuthorizeHook=FlowHooksOf2("oauth:authorize");var OAuthCallbackHook=FlowHooksOf2("oauth:callback");var OAuthProviderCallbackHook=FlowHooksOf2("oauth:provider-callback");var OAuthRegisterHook=FlowHooksOf2("oauth:register");var ElicitRequestHook=FlowHooksOf2("elicitation:request");var ElicitResultHook=FlowHooksOf2("elicitation:result");var SubscribeResourceHook=FlowHooksOf2("resources:subscribe");var UnsubscribeResourceHook=FlowHooksOf2("resources:unsubscribe");var SkillsHttpLlmTxtHook=FlowHooksOf2("skills-http:llm-txt");var SkillsHttpLlmFullTxtHook=FlowHooksOf2("skills-http:llm-full-txt");var SkillsHttpApiHook=FlowHooksOf2("skills-http:api");var WellKnownJwksHook=FlowHooksOf2("well-known.jwks");var WellKnownOAuthServerHook=FlowHooksOf2("well-known.oauth-authorization-server");var WellKnownPrmHook=FlowHooksOf2("well-known.prm");var LoggingSetLevelHook=FlowHooksOf2("logging:set-level");var DEFAULT_TRACING={httpSpans:true,executionSpans:true,hookSpans:false,fetchSpans:true,flowStageEvents:true,transportSpans:true,authSpans:true,oauthSpans:true,elicitationSpans:true,startupReport:true};var ObservabilityPlugin=class extends DynamicPlugin{constructor(options={}){super();this.observeHook=async({flowName,stage,target,flowContext},run)=>{if(target===this)return run();if(this.requestLogsEnabled)currentRequestLog(flowContext)?.addHook(`${flowName}:${stage}`);if(!this.traces("hookSpans"))return run();const owner=target?.constructor?.name;return runInHookSpan(flowContext,{flowName,stage,owner},run)};this.options=resolveOptions(options);this.tracingOpts=this.options.tracing!==false?this.options.tracing:DEFAULT_TRACING}get tracingEnabled(){return this.options.tracing!==false}get requestLogsEnabled(){return this.options.requestLogs!==false}traces(kind){return this.tracingEnabled&&this.tracingOpts[kind]!==false}watchHooks(ctx){if(this.requestLogsEnabled||this.traces("hookSpans"))installHookObserver(ctx,this.observeHook)}annotateRequestLog(ctx,set){if(!this.requestLogsEnabled)return;const flowCtx=ctx;const log=currentRequestLog(ctx);if(log&&flowCtx.state?.input)set(log,flowCtx.state.input)}_httpWillTrace(ctx){if(this.tracingEnabled)onHttpWillTrace(this.tracingOpts,ctx);if(this.options.requestLogs!==false)startRequestLog(ctx,this.options.requestLogs);this.watchHooks(ctx)}_httpWillQuota(ctx){if(this.tracingEnabled)onHttpWillAcquireQuota(ctx)}_httpDidSemaphore(ctx){if(this.tracingEnabled)onHttpDidAcquireQuota(ctx)}_httpWillAuth(ctx){if(this.tracingEnabled)onHttpWillCheckAuth(ctx)}_httpDidAuth(ctx){if(this.tracingEnabled)onHttpDidCheckAuth(ctx);if(this.requestLogsEnabled)recordRequestLogAuth(ctx)}_httpWillRoute(ctx){if(this.tracingEnabled)onHttpWillRoute(ctx)}_httpDidRoute(ctx){if(this.tracingEnabled)onHttpDidRoute(ctx)}_httpFinallyFinalize(ctx){if(this.tracingEnabled)onHttpDidFinalize(ctx);if(this.requestLogsEnabled)void completeRequestLog(ctx)}_toolWillParse(ctx){this.watchHooks(ctx);if(this.tracingEnabled)onToolWillParse(this.tracingOpts,ctx)}_toolWillFind(ctx){if(this.tracingEnabled)onToolWillFindTool(ctx);this.annotateRequestLog(ctx,(log,input)=>log.setToolName(String(input["name"])))}_toolWillCheckAuth(ctx){if(this.tracingEnabled)onToolWillCheckAuth(ctx)}_toolWillCheckAuthorities(ctx){if(this.tracingEnabled)onEntryWillCheckAuthorities(ctx)}_toolDidCheckAuthorities(ctx){if(this.tracingEnabled)onEntryDidCheckAuthorities(ctx)}_toolWillCreateCtx(ctx){if(this.tracingEnabled)onToolWillCreateContext(ctx)}_toolWillValidate(ctx){if(this.tracingEnabled)onToolWillValidateInput(ctx)}_toolWillExecute(ctx){if(this.tracingEnabled)onToolWillExecute(this.tracingOpts,ctx)}_toolDidExecute(ctx){if(this.tracingEnabled)onToolDidExecute(this.tracingOpts,ctx)}_toolWillValidateOut(ctx){if(this.tracingEnabled)onToolWillValidateOutput(ctx)}_toolWillApplyUI(ctx){if(this.tracingEnabled)onToolWillApplyUI(ctx)}_toolFinallyFinalize(ctx){if(this.tracingEnabled)onToolDidFinalize(ctx);if(this.requestLogsEnabled)recordRequestLogFailure(ctx)}_resourceWillParse(ctx){this.watchHooks(ctx);if(this.tracingEnabled)onResourceWillParse(this.tracingOpts,ctx)}_resourceWillFind(ctx){if(this.tracingEnabled)onResourceWillFind(ctx);this.annotateRequestLog(ctx,(log,input)=>log.setResourceUri(String(input["uri"])))}_resourceWillCheckAuthorities(ctx){if(this.tracingEnabled)onEntryWillCheckAuthorities(ctx)}_resourceDidCheckAuthorities(ctx){if(this.tracingEnabled)onEntryDidCheckAuthorities(ctx)}_resourceWillExecute(ctx){if(this.tracingEnabled)onResourceWillExecute(this.tracingOpts,ctx)}_resourceDidExecute(ctx){if(this.tracingEnabled)onResourceDidExecute(ctx)}_resourceFinallyFinalize(ctx){if(this.tracingEnabled)onResourceDidFinalize(ctx);if(this.requestLogsEnabled)recordRequestLogFailure(ctx)}_promptWillParse(ctx){this.watchHooks(ctx);if(this.tracingEnabled)onPromptWillParse(this.tracingOpts,ctx)}_promptWillFind(ctx){if(this.tracingEnabled)onPromptWillFind(ctx);this.annotateRequestLog(ctx,(log,input)=>log.setPromptName(String(input["name"])))}_promptWillCheckAuthorities(ctx){if(this.tracingEnabled)onEntryWillCheckAuthorities(ctx)}_promptDidCheckAuthorities(ctx){if(this.tracingEnabled)onEntryDidCheckAuthorities(ctx)}_promptWillExecute(ctx){if(this.tracingEnabled)onPromptWillExecute(this.tracingOpts,ctx)}_promptDidExecute(ctx){if(this.tracingEnabled)onPromptDidExecute(ctx)}_promptFinallyFinalize(ctx){if(this.tracingEnabled)onPromptDidFinalize(ctx);if(this.requestLogsEnabled)recordRequestLogFailure(ctx)}_agentWillParse(ctx){this.watchHooks(ctx);if(this.tracingEnabled)onAgentWillParse(this.tracingOpts,ctx)}_agentWillFind(ctx){if(this.tracingEnabled)onAgentWillFind(ctx)}_agentWillCheckAuthorities(ctx){if(this.tracingEnabled)onEntryWillCheckAuthorities(ctx)}_agentDidCheckAuthorities(ctx){if(this.tracingEnabled)onEntryDidCheckAuthorities(ctx)}_agentWillExecute(ctx){if(this.tracingEnabled)onAgentWillExecute(this.tracingOpts,ctx)}_agentDidExecute(ctx){if(this.tracingEnabled)onAgentDidExecute(ctx)}_agentFinallyFinalize(ctx){if(this.tracingEnabled)onAgentDidFinalize(ctx)}_listToolsWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("tools/list",this.tracingOpts,ctx)}_listToolsDidFind(ctx){if(this.tracingEnabled)onGenericFlowStage("findTools",ctx)}_listToolsDidFilter(ctx){if(this.tracingEnabled)onGenericFlowStage("filterByAuthorities",ctx)}_listToolsDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_listResourcesWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("resources/list",this.tracingOpts,ctx)}_listResourcesDidFilter(ctx){if(this.tracingEnabled)onGenericFlowStage("filterByAuthorities",ctx)}_listResourcesDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_listTemplatesWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("resources/listTemplates",this.tracingOpts,ctx)}_listTemplatesDidFilter(ctx){if(this.tracingEnabled)onGenericFlowStage("filterByAuthorities",ctx)}_listTemplatesDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_listPromptsWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("prompts/list",this.tracingOpts,ctx)}_listPromptsDidFilter(ctx){if(this.tracingEnabled)onGenericFlowStage("filterByAuthorities",ctx)}_listPromptsDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillSearchWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills/search",this.tracingOpts,ctx)}_skillSearchDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillLoadWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills/load",this.tracingOpts,ctx)}_skillLoadStage(ctx){if(this.tracingEnabled)onGenericFlowStage("loadSkills",ctx)}_skillLoadDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_completionWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("completion/complete",this.tracingOpts,ctx)}_completionDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_sseWillParse(ctx){if(this.tracingEnabled)onTransportWillStart("legacy-sse",this.tracingOpts,ctx)}_sseDidRoute(ctx){if(this.tracingEnabled)onTransportDidRoute(ctx)}_sseDidInit(ctx){if(this.tracingEnabled)onTransportStage("onInitialize",ctx)}_sseDidMsg(ctx){if(this.tracingEnabled)onTransportStage("onMessage",ctx)}_sseDidElicit(ctx){if(this.tracingEnabled)onTransportStage("onElicitResult",ctx)}_sseFinallyCleanup(ctx){if(this.tracingEnabled)onTransportDidFinalize(ctx)}_shttpWillParse(ctx){if(this.tracingEnabled)onTransportWillStart("streamable-http",this.tracingOpts,ctx)}_shttpDidRoute(ctx){if(this.tracingEnabled)onTransportDidRoute(ctx)}_shttpDidInit(ctx){if(this.tracingEnabled)onTransportStage("onInitialize",ctx)}_shttpDidMsg(ctx){if(this.tracingEnabled)onTransportStage("onMessage",ctx)}_shttpDidElicit(ctx){if(this.tracingEnabled)onTransportStage("onElicitResult",ctx)}_shttpDidSse(ctx){if(this.tracingEnabled)onTransportStage("onSseListener",ctx)}_shttpDidExtApps(ctx){if(this.tracingEnabled)onTransportStage("onExtApps",ctx)}_shttpFinallyCleanup(ctx){if(this.tracingEnabled)onTransportDidFinalize(ctx)}_slhttpWillParse(ctx){if(this.tracingEnabled)onTransportWillStart("stateless-http",this.tracingOpts,ctx)}_slhttpDidHandle(ctx){if(this.tracingEnabled)onTransportStage("handleRequest",ctx)}_slhttpFinallyCleanup(ctx){if(this.tracingEnabled)onTransportDidFinalize(ctx)}_authVerifyWill(ctx){if(this.tracingEnabled)onAuthWillStart("auth:verify",this.tracingOpts,ctx)}_authVerifyDidMode(ctx){if(this.tracingEnabled)onAuthDidDetermineMode(ctx)}_authVerifyDidToken(ctx){if(this.tracingEnabled)onAuthStage("verifyToken",ctx)}_authVerifyDidBuild(ctx){if(this.tracingEnabled)onAuthDidFinalize(ctx)}_sessionVerifyWill(ctx){if(this.tracingEnabled)onAuthWillStart("session:verify",this.tracingOpts,ctx)}_sessionVerifyDidJwt(ctx){if(this.tracingEnabled)onAuthStage("verifyIfJwt",ctx)}_sessionVerifyDidBuild(ctx){if(this.tracingEnabled)onAuthDidFinalize(ctx)}_oauthTokenWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/token",this.tracingOpts,ctx)}_oauthTokenDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_oauthAuthzWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/authorize",this.tracingOpts,ctx)}_oauthAuthzDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_oauthCallbackWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/callback",this.tracingOpts,ctx)}_oauthCallbackDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_oauthProviderWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/provider-callback",this.tracingOpts,ctx)}_oauthProviderDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_oauthRegisterWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/register",this.tracingOpts,ctx)}_oauthRegisterDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_elicitReqWill(ctx){if(this.traces("elicitationSpans"))onGenericFlowWillStart("elicitation/request",this.tracingOpts,ctx)}_elicitReqDone(ctx){if(this.traces("elicitationSpans"))onGenericFlowDidFinalize(ctx)}_elicitResWill(ctx){if(this.traces("elicitationSpans"))onGenericFlowWillStart("elicitation/result",this.tracingOpts,ctx)}_elicitResDone(ctx){if(this.traces("elicitationSpans"))onGenericFlowDidFinalize(ctx)}_subscribeWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("resources/subscribe",this.tracingOpts,ctx)}_subscribeDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_unsubscribeWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("resources/unsubscribe",this.tracingOpts,ctx)}_unsubscribeDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillsLlmTxtWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills-http/llm-txt",this.tracingOpts,ctx)}_skillsLlmTxtDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillsLlmFullTxtWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills-http/llm-full-txt",this.tracingOpts,ctx)}_skillsLlmFullTxtDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillsApiWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills-http/api",this.tracingOpts,ctx)}_skillsApiDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_jwksWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("well-known/jwks",this.tracingOpts,ctx)}_jwksDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_oauthServerWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("well-known/oauth-server",this.tracingOpts,ctx)}_oauthServerDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_prmWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("well-known/prm",this.tracingOpts,ctx)}_prmDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_setLevelWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("logging/set-level",this.tracingOpts,ctx)}_setLevelDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_toolDidCreateCtxFetch(ctx){if(this.tracingEnabled)wrapContextFetch(this.tracingOpts,ctx)}_agentDidExecuteMeta(ctx){if(this.tracingEnabled)onAgentDidExecuteEnrich(ctx)}reportStartupTelemetry(data){if(this.traces("startupReport"))reportStartup(data)}};ObservabilityPlugin.defaultOptions={tracing:DEFAULT_TRACING,logging:false,requestLogs:false,stalls:false,devEvents:false};ObservabilityPlugin.dynamicProviders=input=>{const options=resolveOptions(input);const providers=[];if(options.tracing!==false){providers.push({name:"observability:tracer",provide:OTEL_TRACER,useValue:trace6.getTracer("@frontmcp/observability")});providers.push({name:"observability:config",provide:OTEL_CONFIG,useValue:options.tracing});providers.push({name:"observability:telemetry-accessor",provide:TELEMETRY_ACCESSOR,scope:ProviderScope.CONTEXT,inject:()=>[FRONTMCP_CONTEXT2],useFactory:ctx=>new TelemetryAccessor(ctx)});providers.push({name:"observability:telemetry-factory",provide:TELEMETRY_FACTORY,useValue:new TelemetryFactory})}if(options.logging!==false){const loggingOpts=options.logging;const sinks=createSinks(loggingOpts.sinks);const transport=new StructuredLogTransport(sinks,{redactFields:loggingOpts.redactFields,includeStacks:loggingOpts.includeStacks,staticFields:loggingOpts.staticFields},void 0);providers.push({name:"observability:structured-log-transport",provide:StructuredLogTransport,useValue:transport})}if(options.requestLogs!==false){const requestLogOpts=options.requestLogs;providers.push({name:"observability:request-log-collector",provide:REQUEST_LOG_COLLECTOR,scope:ProviderScope.CONTEXT,inject:()=>[FRONTMCP_CONTEXT2],useFactory:ctx=>{return new RequestLogCollector({requestId:ctx.requestId,traceId:ctx.traceContext.traceId,sessionIdHash:sessionTracingId(ctx.sessionId).slice(0,12),scopeId:ctx.scopeId},requestLogOpts)}})}if(options.stalls!==false||options.devEvents!==false){const{stalls,devEvents}=options;providers.push({name:"observability:call-monitor",provide:CallMonitor,inject:()=>[FRONTMCP_LOGGER],useFactory:logger=>new CallMonitor(stalls,devEvents,logger.child("CallMonitor"))})}return providers};__decorateClass([HttpHook.Will("traceRequest",{priority:-1e3})],ObservabilityPlugin.prototype,"_httpWillTrace",1);__decorateClass([HttpHook.Will("acquireQuota",{priority:-1e3})],ObservabilityPlugin.prototype,"_httpWillQuota",1);__decorateClass([HttpHook.Did("acquireSemaphore",{priority:1e3})],ObservabilityPlugin.prototype,"_httpDidSemaphore",1);__decorateClass([HttpHook.Will("checkAuthorization",{priority:-1e3})],ObservabilityPlugin.prototype,"_httpWillAuth",1);__decorateClass([HttpHook.Did("checkAuthorization",{priority:1e3})],ObservabilityPlugin.prototype,"_httpDidAuth",1);__decorateClass([HttpHook.Will("router",{priority:-1e3})],ObservabilityPlugin.prototype,"_httpWillRoute",1);__decorateClass([HttpHook.Did("router",{priority:1e3})],ObservabilityPlugin.prototype,"_httpDidRoute",1);__decorateClass([HttpHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_httpFinallyFinalize",1);__decorateClass([ToolHook2.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillParse",1);__decorateClass([ToolHook2.Will("findTool",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillFind",1);__decorateClass([ToolHook2.Will("checkToolAuthorization",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillCheckAuth",1);__decorateClass([ToolHook2.Will("checkEntryAuthorities",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillCheckAuthorities",1);__decorateClass([ToolHook2.Did("checkEntryAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_toolDidCheckAuthorities",1);__decorateClass([ToolHook2.Will("createToolCallContext",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillCreateCtx",1);__decorateClass([ToolHook2.Will("validateInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillValidate",1);__decorateClass([ToolHook2.Will("execute",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillExecute",1);__decorateClass([ToolHook2.Did("execute",{priority:1e3})],ObservabilityPlugin.prototype,"_toolDidExecute",1);__decorateClass([ToolHook2.Will("validateOutput",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillValidateOut",1);__decorateClass([ToolHook2.Will("applyUI",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillApplyUI",1);__decorateClass([ToolHook2.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_toolFinallyFinalize",1);__decorateClass([ResourceHook2.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_resourceWillParse",1);__decorateClass([ResourceHook2.Will("findResource",{priority:-1e3})],ObservabilityPlugin.prototype,"_resourceWillFind",1);__decorateClass([ResourceHook2.Will("checkEntryAuthorities",{priority:-1e3})],ObservabilityPlugin.prototype,"_resourceWillCheckAuthorities",1);__decorateClass([ResourceHook2.Did("checkEntryAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_resourceDidCheckAuthorities",1);__decorateClass([ResourceHook2.Will("execute",{priority:-1e3})],ObservabilityPlugin.prototype,"_resourceWillExecute",1);__decorateClass([ResourceHook2.Did("execute",{priority:1e3})],ObservabilityPlugin.prototype,"_resourceDidExecute",1);__decorateClass([ResourceHook2.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_resourceFinallyFinalize",1);__decorateClass([PromptHook2.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_promptWillParse",1);__decorateClass([PromptHook2.Will("findPrompt",{priority:-1e3})],ObservabilityPlugin.prototype,"_promptWillFind",1);__decorateClass([PromptHook2.Will("checkEntryAuthorities",{priority:-1e3})],ObservabilityPlugin.prototype,"_promptWillCheckAuthorities",1);__decorateClass([PromptHook2.Did("checkEntryAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_promptDidCheckAuthorities",1);__decorateClass([PromptHook2.Will("execute",{priority:-1e3})],ObservabilityPlugin.prototype,"_promptWillExecute",1);__decorateClass([PromptHook2.Did("execute",{priority:1e3})],ObservabilityPlugin.prototype,"_promptDidExecute",1);__decorateClass([PromptHook2.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_promptFinallyFinalize",1);__decorateClass([AgentCallHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_agentWillParse",1);__decorateClass([AgentCallHook.Will("findAgent",{priority:-1e3})],ObservabilityPlugin.prototype,"_agentWillFind",1);__decorateClass([AgentCallHook.Will("checkEntryAuthorities",{priority:-1e3})],ObservabilityPlugin.prototype,"_agentWillCheckAuthorities",1);__decorateClass([AgentCallHook.Did("checkEntryAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_agentDidCheckAuthorities",1);__decorateClass([AgentCallHook.Will("execute",{priority:-1e3})],ObservabilityPlugin.prototype,"_agentWillExecute",1);__decorateClass([AgentCallHook.Did("execute",{priority:1e3})],ObservabilityPlugin.prototype,"_agentDidExecute",1);__decorateClass([AgentCallHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_agentFinallyFinalize",1);__decorateClass([ListToolsHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_listToolsWill",1);__decorateClass([ListToolsHook.Did("findTools",{priority:1e3})],ObservabilityPlugin.prototype,"_listToolsDidFind",1);__decorateClass([ListToolsHook.Did("filterByAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_listToolsDidFilter",1);__decorateClass([ListToolsHook.Did("parseTools",{priority:1e3})],ObservabilityPlugin.prototype,"_listToolsDone",1);__decorateClass([ListResourcesHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_listResourcesWill",1);__decorateClass([ListResourcesHook.Did("filterByAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_listResourcesDidFilter",1);__decorateClass([ListResourcesHook.Did("parseResources",{priority:1e3})],ObservabilityPlugin.prototype,"_listResourcesDone",1);__decorateClass([ListResourceTemplatesHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_listTemplatesWill",1);__decorateClass([ListResourceTemplatesHook.Did("filterByAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_listTemplatesDidFilter",1);__decorateClass([ListResourceTemplatesHook.Did("parseTemplates",{priority:1e3})],ObservabilityPlugin.prototype,"_listTemplatesDone",1);__decorateClass([ListPromptsHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_listPromptsWill",1);__decorateClass([ListPromptsHook.Did("filterByAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_listPromptsDidFilter",1);__decorateClass([ListPromptsHook.Did("parsePrompts",{priority:1e3})],ObservabilityPlugin.prototype,"_listPromptsDone",1);__decorateClass([SkillSearchHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillSearchWill",1);__decorateClass([SkillSearchHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_skillSearchDone",1);__decorateClass([SkillLoadHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillLoadWill",1);__decorateClass([SkillLoadHook.Will("loadSkills",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillLoadStage",1);__decorateClass([SkillLoadHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_skillLoadDone",1);__decorateClass([CompletionHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_completionWill",1);__decorateClass([CompletionHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_completionDone",1);__decorateClass([LegacySseHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_sseWillParse",1);__decorateClass([LegacySseHook.Did("router",{priority:1e3})],ObservabilityPlugin.prototype,"_sseDidRoute",1);__decorateClass([LegacySseHook.Did("onInitialize",{priority:1e3})],ObservabilityPlugin.prototype,"_sseDidInit",1);__decorateClass([LegacySseHook.Did("onMessage",{priority:1e3})],ObservabilityPlugin.prototype,"_sseDidMsg",1);__decorateClass([LegacySseHook.Did("onElicitResult",{priority:1e3})],ObservabilityPlugin.prototype,"_sseDidElicit",1);__decorateClass([LegacySseHook.Finally("cleanup",{priority:1e3})],ObservabilityPlugin.prototype,"_sseFinallyCleanup",1);__decorateClass([StreamableHttpHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_shttpWillParse",1);__decorateClass([StreamableHttpHook.Did("router",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidRoute",1);__decorateClass([StreamableHttpHook.Did("onInitialize",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidInit",1);__decorateClass([StreamableHttpHook.Did("onMessage",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidMsg",1);__decorateClass([StreamableHttpHook.Did("onElicitResult",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidElicit",1);__decorateClass([StreamableHttpHook.Did("onSseListener",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidSse",1);__decorateClass([StreamableHttpHook.Did("onExtApps",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidExtApps",1);__decorateClass([StreamableHttpHook.Finally("cleanup",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpFinallyCleanup",1);__decorateClass([StatelessHttpHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_slhttpWillParse",1);__decorateClass([StatelessHttpHook.Did("handleRequest",{priority:1e3})],ObservabilityPlugin.prototype,"_slhttpDidHandle",1);__decorateClass([StatelessHttpHook.Finally("cleanup",{priority:1e3})],ObservabilityPlugin.prototype,"_slhttpFinallyCleanup",1);__decorateClass([AuthVerifyHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_authVerifyWill",1);__decorateClass([AuthVerifyHook.Did("determineAuthMode",{priority:1e3})],ObservabilityPlugin.prototype,"_authVerifyDidMode",1);__decorateClass([AuthVerifyHook.Did("verifyToken",{priority:1e3})],ObservabilityPlugin.prototype,"_authVerifyDidToken",1);__decorateClass([AuthVerifyHook.Did("buildAuthorization",{priority:1e3})],ObservabilityPlugin.prototype,"_authVerifyDidBuild",1);__decorateClass([SessionVerifyHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_sessionVerifyWill",1);__decorateClass([SessionVerifyHook.Did("verifyIfJwt",{priority:1e3})],ObservabilityPlugin.prototype,"_sessionVerifyDidJwt",1);__decorateClass([SessionVerifyHook.Did("buildAuthorizedOutput",{priority:1e3})],ObservabilityPlugin.prototype,"_sessionVerifyDidBuild",1);__decorateClass([OAuthTokenHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthTokenWill",1);__decorateClass([OAuthTokenHook.Did("buildTokenResponse",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthTokenDone",1);__decorateClass([OAuthAuthorizeHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthAuthzWill",1);__decorateClass([OAuthAuthorizeHook.Did("buildAuthorizeOutput",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthAuthzDone",1);__decorateClass([OAuthCallbackHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthCallbackWill",1);__decorateClass([OAuthCallbackHook.Did("redirectToClient",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthCallbackDone",1);__decorateClass([OAuthProviderCallbackHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthProviderWill",1);__decorateClass([OAuthProviderCallbackHook.Did("handleNextProviderOrComplete",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthProviderDone",1);__decorateClass([OAuthRegisterHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthRegisterWill",1);__decorateClass([OAuthRegisterHook.Did("respondRegistration",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthRegisterDone",1);__decorateClass([ElicitRequestHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_elicitReqWill",1);__decorateClass([ElicitRequestHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_elicitReqDone",1);__decorateClass([ElicitResultHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_elicitResWill",1);__decorateClass([ElicitResultHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_elicitResDone",1);__decorateClass([SubscribeResourceHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_subscribeWill",1);__decorateClass([SubscribeResourceHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_subscribeDone",1);__decorateClass([UnsubscribeResourceHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_unsubscribeWill",1);__decorateClass([UnsubscribeResourceHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_unsubscribeDone",1);__decorateClass([SkillsHttpLlmTxtHook.Will("checkEnabled",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillsLlmTxtWill",1);__decorateClass([SkillsHttpLlmTxtHook.Did("generateContent",{priority:1e3})],ObservabilityPlugin.prototype,"_skillsLlmTxtDone",1);__decorateClass([SkillsHttpLlmFullTxtHook.Will("checkEnabled",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillsLlmFullTxtWill",1);__decorateClass([SkillsHttpLlmFullTxtHook.Did("generateContent",{priority:1e3})],ObservabilityPlugin.prototype,"_skillsLlmFullTxtDone",1);__decorateClass([SkillsHttpApiHook.Will("checkEnabled",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillsApiWill",1);__decorateClass([SkillsHttpApiHook.Did("handleRequest",{priority:1e3})],ObservabilityPlugin.prototype,"_skillsApiDone",1);__decorateClass([WellKnownJwksHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_jwksWill",1);__decorateClass([WellKnownJwksHook.Did("collectData",{priority:1e3})],ObservabilityPlugin.prototype,"_jwksDone",1);__decorateClass([WellKnownOAuthServerHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthServerWill",1);__decorateClass([WellKnownOAuthServerHook.Did("collectData",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthServerDone",1);__decorateClass([WellKnownPrmHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_prmWill",1);__decorateClass([WellKnownPrmHook.Did("collectData",{priority:1e3})],ObservabilityPlugin.prototype,"_prmDone",1);__decorateClass([LoggingSetLevelHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_setLevelWill",1);__decorateClass([LoggingSetLevelHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_setLevelDone",1);__decorateClass([ToolHook2.Did("createToolCallContext",{priority:999})],ObservabilityPlugin.prototype,"_toolDidCreateCtxFetch",1);__decorateClass([AgentCallHook.Did("execute",{priority:999})],ObservabilityPlugin.prototype,"_agentDidExecuteMeta",1);ObservabilityPlugin=__decorateClass([Plugin({name:"observability",description:"Full-system OpenTelemetry instrumentation, structured logging, and request logs",providers:[],contextExtensions:[{property:"telemetry",token:TELEMETRY_ACCESSOR,errorMessage:"ObservabilityPlugin is not installed or tracing is disabled. Add ObservabilityPlugin.init() to your plugins array."}]})],ObservabilityPlugin);function resolveOptions(input){return{tracing:resolveTracingOptions(input.tracing),logging:resolveLoggingOptions(input.logging),requestLogs:resolveRequestLogOptions(input.requestLogs),stalls:resolveStallOptions(input.stalls),devEvents:resolveDevEventsOptions(input.devEvents)}}function resolveTracingOptions(input){if(input===false)return false;if(input===true||input===void 0)return DEFAULT_TRACING;return{...DEFAULT_TRACING,...input}}function resolveLoggingOptions(input){if(input===false||input===void 0)return false;if(input===true)return{};return input}function resolveRequestLogOptions(input){if(input===false||input===void 0)return false;if(input===true)return{};return input}import{trace as trace7}from"@opentelemetry/api";var TRACEPARENT_HEADER="traceparent";var FrontMcpPropagator=class{inject(context,carrier,setter){const span=trace7.getSpan(context);if(!span)return;const sc=span.spanContext();if(!sc||!isValidSpanContext(sc))return;const flags=sc.traceFlags.toString(16).padStart(2,"0");const traceparent=`00-${sc.traceId}-${sc.spanId}-${flags}`;setter.set(carrier,TRACEPARENT_HEADER,traceparent)}extract(context,carrier,getter){const traceparent=getter.get(carrier,TRACEPARENT_HEADER);const value=Array.isArray(traceparent)?traceparent[0]:traceparent;if(!value)return context;const parsed=parseTraceparent(value);if(!parsed)return context;const spanContext={traceId:parsed.traceId,spanId:parsed.parentId,traceFlags:parsed.traceFlags,isRemote:true};const span=trace7.wrapSpanContext(spanContext);return trace7.setSpan(context,span)}fields(){return[TRACEPARENT_HEADER]}};function parseTraceparent(value){const parts=value.split("-");if(parts.length!==4)return null;const[version,traceId,parentId,flags]=parts;if(version!=="00")return null;if(!/^[a-f0-9]{32}$/i.test(traceId)||traceId==="00000000000000000000000000000000")return null;if(!/^[a-f0-9]{16}$/i.test(parentId)||parentId==="0000000000000000")return null;if(!/^[0-9a-fA-F]{2}$/.test(flags))return null;const traceFlags=parseInt(flags,16);return{traceId:traceId.toLowerCase(),parentId:parentId.toLowerCase(),traceFlags}}function isValidSpanContext(sc){return sc.traceId!=="00000000000000000000000000000000"&&sc.spanId!=="0000000000000000"&&sc.traceId.length===32&&sc.spanId.length===16}function setupOTel(options){const serviceName=options?.serviceName??process.env["OTEL_SERVICE_NAME"]??"frontmcp-server";const exporterType=options?.exporter??"console";const endpoint=options?.endpoint??process.env["OTEL_EXPORTER_OTLP_ENDPOINT"]??"http://localhost:4318";let traceExporter;if(exporterType==="otlp"){try{const{OTLPTraceExporter}=__require("@opentelemetry/exporter-trace-otlp-http");traceExporter=new OTLPTraceExporter({url:`${endpoint}/v1/traces`})}catch{throw new Error("setupOTel: @opentelemetry/exporter-trace-otlp-http is required for OTLP export. Install it with: npm install @opentelemetry/exporter-trace-otlp-http")}}else if(exporterType==="console"){const{ConsoleSpanExporter}=__require("@opentelemetry/sdk-trace-base");traceExporter=new ConsoleSpanExporter}try{const{NodeSDK}=__require("@opentelemetry/sdk-node");const{resourceFromAttributes}=__require("@opentelemetry/resources");const{ATTR_SERVICE_NAME,ATTR_SERVICE_VERSION}=__require("@opentelemetry/semantic-conventions");const resource=resourceFromAttributes({[ATTR_SERVICE_NAME]:serviceName,...options?.serviceVersion?{[ATTR_SERVICE_VERSION]:options.serviceVersion}:{}});const sdk=new NodeSDK({resource,traceExporter});sdk.start();return async()=>{await sdk.shutdown()}}catch{throw new Error("setupOTel: @opentelemetry/sdk-node is required. Install it with: npm install @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/semantic-conventions")}}import{SpanKind as SpanKind14,SpanStatusCode as SpanStatusCode5}from"@opentelemetry/api";var RESET="\x1B[0m";var DIM="\x1B[2m";var BOLD="\x1B[1m";var CYAN="\x1B[36m";var GREEN="\x1B[32m";var RED="\x1B[31m";var YELLOW="\x1B[33m";var KIND_LABELS={[SpanKind14.INTERNAL]:"INTERNAL",[SpanKind14.SERVER]:"SERVER",[SpanKind14.CLIENT]:"CLIENT",[SpanKind14.PRODUCER]:"PRODUCER",[SpanKind14.CONSUMER]:"CONSUMER"};var SHOW_ATTRS=new Set(["rpc.system","rpc.method","rpc.service","mcp.method.name","mcp.session.id","mcp.component.type","mcp.component.key","http.request.method","http.response.status_code","url.path","frontmcp.tool.name","frontmcp.tool.owner","frontmcp.transport.type","frontmcp.transport.request_type","frontmcp.auth.mode","frontmcp.auth.result","frontmcp.flow.name","enduser.id"]);var PrettySpanExporter=class{constructor(){this.useAnsi=typeof process!=="undefined"&&!!process.stdout?.isTTY}export(spans,resultCallback){for(const span of spans){console.log(this.format(span))}resultCallback({code:0})}shutdown(){return Promise.resolve()}format(span){const traceShort=span.spanContext().traceId.slice(0,8);const durationMs=(span.duration[0]*1e3+span.duration[1]/1e6).toFixed(1);const kind=KIND_LABELS[span.kind]??"UNKNOWN";const statusOk=span.status.code!==SpanStatusCode5.ERROR;const attrs=Object.entries(span.attributes).filter(([k])=>SHOW_ATTRS.has(k)).map(([k,v])=>{const short=k.replace("frontmcp.","").replace("mcp.","");return`${short}=${v}`}).join(" ");const eventCount=span.events.length;const eventSummary=eventCount>0?` (${eventCount} events)`:"";if(this.useAnsi){const statusColor=statusOk?GREEN:RED;const kindColor=span.kind===SpanKind14.SERVER?CYAN:DIM;return[`${DIM}\u21B3${RESET}`,`${BOLD}${statusColor}SPAN${RESET}`,`${BOLD}${span.name}${RESET}`,`${DIM}[${traceShort}]${RESET}`,`${YELLOW}${durationMs}ms${RESET}`,`${kindColor}${kind}${RESET}`,attrs?`${DIM}${attrs}${RESET}`:"",eventSummary?`${DIM}${eventSummary}${RESET}`:""].filter(Boolean).join(" ")}return["\u21B3 SPAN",span.name,`[${traceShort}]`,`${durationMs}ms`,kind,attrs,eventSummary].filter(Boolean).join(" ")}};init_winston_sink();init_pino_sink();init_otlp_sink();import{redactFields as redactFields2}from"@frontmcp/utils";var METRIC_NAME_REGEX=/^[a-zA-Z_:][a-zA-Z0-9_:]*$/;var LABEL_NAME_REGEX=/^[a-zA-Z_][a-zA-Z0-9_]*$/;var PROMETHEUS_CONTENT_TYPE="text/plain; version=0.0.4; charset=utf-8";function escapeLabelValue(value){return value.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}function sortedLabelString(attributes){const keys=Object.keys(attributes).filter(k=>LABEL_NAME_REGEX.test(k)).sort();if(keys.length===0)return"";const pairs=keys.map(k=>`${k}="${escapeLabelValue(attributes[k]??"")}"`);return`{${pairs.join(",")}}`}function formatFloat(value){if(!Number.isFinite(value))return"";if(Number.isInteger(value))return String(value);return String(value)}function renderPrometheusExposition(counters,gauges=[],options={}){const byName=new Map;for(const entry of counters){if(!METRIC_NAME_REGEX.test(entry.name))continue;const valueStr=formatFloat(entry.count);if(valueStr==="")continue;const labels=sortedLabelString(entry.attributes??{});const line=`${entry.name}${labels} ${valueStr}`;let group=byName.get(entry.name);if(!group){group={type:"counter",help:options.counterHelp?.[entry.name],lines:[]};byName.set(entry.name,group)}group.lines.push(line)}for(const entry of gauges){if(!METRIC_NAME_REGEX.test(entry.name))continue;const valueStr=formatFloat(entry.value);if(valueStr==="")continue;const labels=sortedLabelString(entry.attributes??{});const line=`${entry.name}${labels} ${valueStr}`;let group=byName.get(entry.name);if(!group){group={type:"gauge",help:entry.help,lines:[]};byName.set(entry.name,group)}else if(entry.help&&!group.help){group.help=entry.help}group.lines.push(line)}if(byName.size===0)return"";const sortedNames=Array.from(byName.keys()).sort();const blocks=[];for(const name of sortedNames){const group=byName.get(name);if(!group)continue;const block=[];if(group.help){block.push(`# HELP ${name} ${group.help.replace(/\n/g," ")}`)}block.push(`# TYPE ${name} ${group.type}`);block.push(...group.lines.slice().sort());blocks.push(block.join("\n"))}return blocks.join("\n")+"\n"}function renderJsonExposition(counters,gauges=[]){return{counters:counters.filter(c=>METRIC_NAME_REGEX.test(c.name)&&Number.isFinite(c.count)).map(c=>({name:c.name,count:c.count,attributes:{...c.attributes??{}}})),gauges:gauges.filter(g=>METRIC_NAME_REGEX.test(g.name)&&Number.isFinite(g.value)).map(g=>({name:g.name,value:g.value,attributes:{...g.attributes??{}},...g.help?{help:g.help}:{}}))}}import{readdirSync}from"@frontmcp/utils";var NS_PER_SECOND=1e9;var MICROS_PER_SECOND=1e6;function probeSafely(probe){try{return probe()}catch{return void 0}}function defaultMonitorEventLoopDelay(){try{const{monitorEventLoopDelay}=__require("node:perf_hooks");const histogram=monitorEventLoopDelay({resolution:10});histogram.enable();return histogram}catch{return void 0}}function defaultGetActiveHandles(){const proc=process;if(typeof proc._getActiveHandles!=="function")return void 0;try{return proc._getActiveHandles()}catch{return void 0}}function defaultGetActiveRequests(){const proc=process;if(typeof proc._getActiveRequests!=="function")return void 0;try{return proc._getActiveRequests()}catch{return void 0}}function defaultReadFdCount(){if(process.platform!=="linux")return void 0;try{return readdirSync("/proc/self/fd").length}catch{return void 0}}var ProcessStatsCollector=class{constructor(init={}){this.options=init.options??{};this.cpuUsage=init.cpuUsage??(prev=>process.cpuUsage(prev));this.memoryUsage=init.memoryUsage??(()=>process.memoryUsage());this.uptime=init.uptime??(()=>process.uptime());this.getActiveHandles=init.getActiveHandles??defaultGetActiveHandles;this.getActiveRequests=init.getActiveRequests??defaultGetActiveRequests;this.readFdCount=init.readFdCount??defaultReadFdCount;this.cpuStart=probeSafely(()=>this.cpuUsage());if(this.options.eventLoopLag!==false){this.histogram=init.monitorEventLoopDelay?init.monitorEventLoopDelay():defaultMonitorEventLoopDelay()}}collect(){const entries=[];this.cpuStart??=probeSafely(()=>this.cpuUsage());const cpu=this.cpuStart&&probeSafely(()=>this.cpuUsage(this.cpuStart));if(cpu){entries.push({name:"frontmcp_process_cpu_seconds_total",value:cpu.user/MICROS_PER_SECOND,attributes:{mode:"user"},help:"CPU time consumed since collector start, by mode (seconds)"});entries.push({name:"frontmcp_process_cpu_seconds_total",value:cpu.system/MICROS_PER_SECOND,attributes:{mode:"system"}})}const mem=probeSafely(()=>this.memoryUsage());if(mem&&mem.rss>0){entries.push({name:"frontmcp_process_resident_memory_bytes",value:mem.rss,help:"Resident memory size in bytes"});entries.push({name:"frontmcp_process_heap_bytes",value:mem.heapTotal,help:"Total V8 heap size in bytes"});entries.push({name:"frontmcp_process_heap_used_bytes",value:mem.heapUsed,help:"Used V8 heap size in bytes"});entries.push({name:"frontmcp_process_external_bytes",value:mem.external,help:"Memory used by C++ objects bound to JS in bytes"})}const uptime=probeSafely(()=>this.uptime());if(uptime!==void 0&&uptime>0){entries.push({name:"frontmcp_process_uptime_seconds",value:uptime,help:"Time since process start in seconds"})}const histogram=this.options.eventLoopLag!==false?this.histogram:void 0;const lag=histogram&&probeSafely(()=>{const sample={meanSeconds:histogram.mean/NS_PER_SECOND,p99Seconds:histogram.percentile(99)/NS_PER_SECOND};histogram.reset();return sample});if(lag){const{meanSeconds,p99Seconds}=lag;if(Number.isFinite(meanSeconds)){entries.push({name:"frontmcp_nodejs_eventloop_lag_seconds",value:meanSeconds,attributes:{quantile:"mean"},help:"Event-loop lag in seconds, sampled at 10ms resolution since the last scrape"})}if(Number.isFinite(p99Seconds)){entries.push({name:"frontmcp_nodejs_eventloop_lag_seconds",value:p99Seconds,attributes:{quantile:"p99"}})}}if(this.options.activeHandles!==false){const handles=this.getActiveHandles?.();if(handles!==void 0){entries.push({name:"frontmcp_nodejs_active_handles",value:handles.length,help:"Currently active libuv handles (sockets, timers, etc.)"})}const requests=this.getActiveRequests?.();if(requests!==void 0){entries.push({name:"frontmcp_nodejs_active_requests",value:requests.length,help:"Currently active libuv requests (file I/O, DNS, etc.)"})}}if(this.options.fdCount!==false){const fdCount=this.readFdCount();if(typeof fdCount==="number"){entries.push({name:"frontmcp_nodejs_open_fds",value:fdCount,help:"Number of open file descriptors (Linux only)"})}}return entries}close(){this.histogram?.disable?.()}};function createTestTracer(name="test"){const sdkTraceBase=__require("@opentelemetry/sdk-trace-base");const exporter=new sdkTraceBase.InMemorySpanExporter;const provider=new sdkTraceBase.BasicTracerProvider({spanProcessors:[new sdkTraceBase.SimpleSpanProcessor(exporter)]});const tracer=provider.getTracer(name);return{tracer,exporter,provider,cleanup:async()=>{exporter.reset();await provider.forceFlush();await provider.shutdown()}}}function getFinishedSpans(exporter){return exporter.getFinishedSpans()}function assertSpanExists(spans,name){const match=spans.find(s=>s.name===name);if(!match){const names=spans.map(s=>s.name).join(", ");throw new Error(`Expected span "${name}" but found: [${names}]`)}return match}function assertSpanAttribute(span,key,value){const actual=span.attributes[key];if(actual!==value){throw new Error(`Expected span "${span.name}" attribute "${key}" to be ${JSON.stringify(value)} but got ${JSON.stringify(actual)}`)}}function findSpan(spans,name){return spans.find(s=>s.name===name)}function findSpansByAttribute(spans,key,value){return spans.filter(s=>s.attributes[key]===value)}export{CallMonitor,CallbackSink,ConsoleSink,DevEventStream,EnduserAttributes,FrontMcpAttributes,FrontMcpPropagator,HttpAttributes,InFlightCalls,IpcDevEventSink,JsonlFileSink,KNOWN_BUNDLE_SOURCES,KNOWN_ERROR_REASONS,LOG_LEVEL_TO_OTEL_SEVERITY,McpAttributes,OTEL_CONFIG,OTEL_TRACER,ObservabilityConfigurationError,ObservabilityPlugin,OtlpSink,PROMETHEUS_CONTENT_TYPE,PinoSink,PrettySpanExporter,ProcessStatsCollector,REQUEST_LOG_COLLECTOR,RequestLogCollector,RpcAttributes,STALL_SECONDS_COUNTER,StallDetector,StdoutSink,StructuredLogTransport,TELEMETRY_ACCESSOR,TELEMETRY_FACTORY,TelemetryAccessor,TelemetryFactory,TelemetrySpan,WinstonSink,assertSpanAttribute,assertSpanExists,countStall,createCounter,createOTelContextFromTrace,createSink,createSinks,createTestTracer,describeStall,emitStartupReport,endSpanError,endSpanOk,findSpan,findSpansByAttribute,frontmcpToOTelSpanContext,getCounterTotal,getFinishedSpans,getMetricSnapshot,normalizeBundleSource,normalizeErrorReason,otelToFrontmcpContext,recordHookEvent,redactFields2 as redactFields,renderJsonExposition,renderPrometheusExposition,reportStartup,resetCounterCacheForTesting,resetMetricSnapshot,resetTelemetrySnapshotForTesting,sessionTracingId,setAuthMode,setAuthResult,setFetchResponseStatus,setHttpResponseStatus,setTransportRequestType,setupOTel,startAuthSpan,startFetchSpan,startHookSpan,startHttpServerSpan,startPromptSpan,startResourceSpan,startRpcSpan,startSpan,startToolSpan,startTransportSpan,withSpan};
4
+ var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __require=(x=>typeof require!=="undefined"?require:typeof Proxy!=="undefined"?new Proxy(x,{get:(a,b)=>(typeof require!=="undefined"?require:a)[b]}):x)(function(x){if(typeof require!=="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+x+'" is not supported')});var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var __decorateClass=(decorators,target,key,kind)=>{var result=kind>1?void 0:kind?__getOwnPropDesc(target,key):target;for(var i=decorators.length-1,decorator;i>=0;i--)if(decorator=decorators[i])result=(kind?decorator(target,key,result):decorator(result))||result;if(kind&&result)__defProp(target,key,result);return result};var winston_sink_exports={};__export(winston_sink_exports,{WinstonSink:()=>WinstonSink});function mapToWinstonLevel(level){switch(level){case"debug":case"verbose":return"debug";case"info":return"info";case"warn":return"warn";case"error":return"error";default:return"info"}}var WinstonSink;var init_winston_sink=__esm({"libs/observability/src/logging/sinks/winston.sink.ts"(){"use strict";WinstonSink=class{constructor(logger){this.logger=logger}write(entry){const{message,level,...meta}=entry;const winstonLevel=mapToWinstonLevel(level);switch(winstonLevel){case"debug":this.logger.debug(message,meta);break;case"info":this.logger.info(message,meta);break;case"warn":this.logger.warn(message,meta);break;case"error":this.logger.error(message,meta);break}}}}});var pino_sink_exports={};__export(pino_sink_exports,{PinoSink:()=>PinoSink});function mapToPinoLevel(level){switch(level){case"debug":case"verbose":return"debug";case"info":return"info";case"warn":return"warn";case"error":return"error";default:return"info"}}var PinoSink;var init_pino_sink=__esm({"libs/observability/src/logging/sinks/pino.sink.ts"(){"use strict";PinoSink=class{constructor(logger){this.logger=logger}write(entry){const{message,level,...obj}=entry;const pinoLevel=mapToPinoLevel(level);switch(pinoLevel){case"debug":this.logger.debug(obj,message);break;case"info":this.logger.info(obj,message);break;case"warn":this.logger.warn(obj,message);break;case"error":this.logger.error(obj,message);break}}}}});var otlp_sink_exports={};__export(otlp_sink_exports,{OtlpSink:()=>OtlpSink});var OtlpSink;var init_otlp_sink=__esm({"libs/observability/src/logging/sinks/otlp.sink.ts"(){"use strict";OtlpSink=class{constructor(options){this.batch=[];let base=options.endpoint;while(base.endsWith("/")){base=base.slice(0,-1)}this.endpoint=`${base}/v1/logs`;this.headers={"Content-Type":"application/json",...options.headers??{}};this.batchSize=options.batchSize??100;this.maxQueueSize=options.maxQueueSize??5e3;this.serviceName=options.serviceName??(typeof process!=="undefined"?process.env?.["OTEL_SERVICE_NAME"]:void 0)??"frontmcp-server";const flushMs=options.flushIntervalMs??5e3;if(flushMs>0){this.flushTimer=setInterval(()=>{void this.flush()},flushMs);if(this.flushTimer&&typeof this.flushTimer==="object"&&"unref"in this.flushTimer){this.flushTimer.unref()}}}write(entry){this.batch.push(entry);this.enforceCapacity();if(this.batch.length>=this.batchSize){void this.flush()}}async flush(){if(this.batch.length===0)return;const entries=this.batch.splice(0);const payload=this.buildOtlpPayload(entries);try{const controller=new AbortController;const timeout=setTimeout(()=>controller.abort(),1e4);try{const response=await fetch(this.endpoint,{method:"POST",headers:this.headers,body:JSON.stringify(payload),signal:controller.signal});clearTimeout(timeout);if(!response.ok){const body=await response.text().catch(()=>"");console.error(`[OtlpSink] Export failed: HTTP ${response.status} \u2014 ${body.slice(0,200)}`);this.requeue(entries)}}catch(err){clearTimeout(timeout);console.debug(`[OtlpSink] Export error (${entries.length} entries): ${err instanceof Error?err.message:err}`);this.requeue(entries)}}catch{}}requeue(entries){this.batch.unshift(...entries);this.enforceCapacity()}enforceCapacity(){if(this.batch.length>this.maxQueueSize){this.batch.splice(0,this.batch.length-this.maxQueueSize)}}async close(){if(this.flushTimer){clearInterval(this.flushTimer);this.flushTimer=void 0}await this.flush()}buildOtlpPayload(entries){return{resourceLogs:[{resource:{attributes:[{key:"service.name",value:{stringValue:this.serviceName}}]},scopeLogs:[{scope:{name:"@frontmcp/observability"},logRecords:entries.map(entry=>this.entryToLogRecord(entry))}]}]}}entryToLogRecord(entry){const attrs=[];const record={timeUnixNano:String(new Date(entry.timestamp).getTime()*1e6),severityNumber:entry.severity_number,severityText:entry.level.toUpperCase(),body:{stringValue:entry.message},attributes:attrs};if(entry.trace_id){record.traceId=entry.trace_id}if(entry.span_id){record.spanId=entry.span_id}if(entry.trace_flags!==void 0){record.flags=entry.trace_flags}if(entry.request_id){attrs.push({key:"frontmcp.request.id",value:{stringValue:entry.request_id}})}if(entry.session_id_hash){attrs.push({key:"mcp.session.id",value:{stringValue:entry.session_id_hash}})}if(entry.scope_id){attrs.push({key:"frontmcp.scope.id",value:{stringValue:entry.scope_id}})}if(entry.flow_name){attrs.push({key:"frontmcp.flow.name",value:{stringValue:entry.flow_name}})}if(entry.prefix){attrs.push({key:"log.prefix",value:{stringValue:entry.prefix}})}if(entry.elapsed_ms!==void 0){attrs.push({key:"elapsed_ms",value:Number.isInteger(entry.elapsed_ms)?{intValue:String(entry.elapsed_ms)}:{doubleValue:entry.elapsed_ms}})}if(entry.error){attrs.push({key:"error.type",value:{stringValue:entry.error.type}});attrs.push({key:"error.message",value:{stringValue:entry.error.message}});if(entry.error.code){attrs.push({key:"error.code",value:{stringValue:entry.error.code}})}if(entry.error.error_id){attrs.push({key:"error.id",value:{stringValue:entry.error.error_id}})}if(entry.error.stack){attrs.push({key:"error.stack",value:{stringValue:entry.error.stack}})}}if(entry.attributes){for(const[key,value]of Object.entries(entry.attributes)){if(value==null)continue;if(typeof value==="string"){attrs.push({key,value:{stringValue:value}})}else if(typeof value==="number"){attrs.push({key,value:Number.isInteger(value)?{intValue:String(value)}:{doubleValue:value}})}else if(typeof value==="boolean"){attrs.push({key,value:{boolValue:value}})}else{attrs.push({key,value:{stringValue:JSON.stringify(value)}})}}}return record}}}});import{trace as trace6}from"@opentelemetry/api";import{AgentCallHook,DynamicPlugin,FlowHooksOf as FlowHooksOf2,FRONTMCP_CONTEXT as FRONTMCP_CONTEXT2,FRONTMCP_LOGGER,HttpHook,ListResourcesHook,ListResourceTemplatesHook,ListToolsHook,Plugin,ProviderScope,ResourceHook as ResourceHook2,ToolHook as ToolHook2}from"@frontmcp/sdk";var CallbackSink=class{constructor(fn){this.fn=fn}write(entry){this.fn(entry)}};var ConsoleSink=class{write(entry){const method=levelToConsoleMethod(entry.level);const formatted=formatEntry(entry);method(formatted)}};function formatEntry(entry){const useAnsi=typeof process!=="undefined"&&!!process.stdout?.isTTY;const ts=entry.timestamp.slice(11,23);const level=entry.level.toUpperCase().padEnd(7);const traceShort=entry.trace_id?entry.trace_id.slice(0,8):"";const reqShort=entry.request_id?entry.request_id.slice(0,8):"";const parts=[];const DIM2=useAnsi?"\x1B[2m":"";const BOLD2=useAnsi?"\x1B[1m":"";const RESET2=useAnsi?"\x1B[0m":"";const levelColor=useAnsi?LEVEL_COLORS[entry.level]??"":"";parts.push(`${DIM2}[${ts}]${RESET2}`);parts.push(`${BOLD2}${levelColor}${level}${RESET2}`);if(traceShort||reqShort){parts.push(`${DIM2}[${traceShort}${reqShort?":"+reqShort:""}]${RESET2}`)}if(entry.prefix)parts.push(`${DIM2}[${entry.prefix}]${RESET2}`);parts.push(entry.message);if(entry.attributes&&Object.keys(entry.attributes).length>0){const attrs=Object.entries(entry.attributes).map(([k,v])=>`${k}=${typeof v==="string"?v:JSON.stringify(v)}`).join(" ");parts.push(`${DIM2}{ ${attrs} }${RESET2}`)}if(entry.error){parts.push(`[${entry.error.type}: ${entry.error.message}]`)}if(entry.elapsed_ms!==void 0){parts.push(`${DIM2}(${entry.elapsed_ms}ms)${RESET2}`)}return parts.join(" ")}var LEVEL_COLORS={debug:"\x1B[34m",verbose:"\x1B[90m",info:"\x1B[32m",warn:"\x1B[33m",error:"\x1B[31m"};function levelToConsoleMethod(level){switch(level){case"debug":case"verbose":return console.debug;case"info":return console.info;case"warn":return console.warn;case"error":return console.error;default:return console.log}}function defaultStream(){const flag=typeof process!=="undefined"?process.env?.["FRONTMCP_STDIO"]:void 0;return flag==="1"||flag==="true"?process.stderr:process.stdout}var StdoutSink=class{constructor(options){this.stream=options?.stream??defaultStream();this.pretty=options?.pretty??false}write(entry){const line=this.pretty?JSON.stringify(entry,null,2):JSON.stringify(entry);this.stream.write(line+"\n")}};function createSink(config){switch(config.type){case"stdout":return new StdoutSink({stream:config.stream,pretty:config.pretty});case"console":return new ConsoleSink;case"winston":{const{WinstonSink:WinstonSink2}=(init_winston_sink(),__toCommonJS(winston_sink_exports));return new WinstonSink2(config.logger)}case"pino":{const{PinoSink:PinoSink2}=(init_pino_sink(),__toCommonJS(pino_sink_exports));return new PinoSink2(config.logger)}case"callback":return new CallbackSink(config.fn);case"otlp":{const{OtlpSink:OtlpSink2}=(init_otlp_sink(),__toCommonJS(otlp_sink_exports));return new OtlpSink2({endpoint:config.endpoint??(typeof process!=="undefined"?process.env?.["OTEL_EXPORTER_OTLP_ENDPOINT"]:void 0)??"http://localhost:4318",headers:config.headers,batchSize:config.batchSize,flushIntervalMs:config.flushIntervalMs,serviceName:config.serviceName})}default:throw new Error(`Unknown sink type: ${config.type}`)}}function createSinks(configs){if(configs&&configs.length>0){return configs.map(createSink)}return[]}import{LogLevelName,LogTransport,LogTransportInterface}from"@frontmcp/sdk";import{redactFields}from"@frontmcp/utils";var LOG_LEVEL_TO_OTEL_SEVERITY={debug:5,verbose:6,info:9,warn:13,error:17};var StructuredLogTransport=class extends LogTransportInterface{constructor(sinks,options,contextAccessor){super();this.sinks=sinks;this.redactFieldNames=options?.redactFields??[];this.includeStacks=options?.includeStacks??true;this.staticFields=options?.staticFields??{};this.getContext=contextAccessor}log(rec){const entry=this.buildEntry(rec);if(this.onEntry){try{this.onEntry(entry)}catch{}}for(const sink of this.sinks){try{sink.write(entry)}catch{}}}buildEntry(rec){const levelName=LogLevelName[rec.level]??"info";const entry={...this.staticFields,timestamp:rec.timestamp.toISOString(),level:levelName,severity_number:LOG_LEVEL_TO_OTEL_SEVERITY[levelName]??9,message:String(rec.message)};if(rec.prefix){entry.prefix=rec.prefix}const ctx=this.getContext?.();if(ctx){entry.trace_id=ctx.traceContext.traceId;entry.span_id=ctx.traceContext.parentId;entry.trace_flags=ctx.traceContext.traceFlags;entry.request_id=ctx.requestId;entry.session_id_hash=ctx.sessionIdHash;entry.scope_id=ctx.scopeId;if(ctx.flowName){entry.flow_name=ctx.flowName}entry.elapsed_ms=ctx.elapsed}this.processArgs(rec.args,entry);return entry}processArgs(args,entry){const attributes={};let hasAttributes=false;for(const arg of args){if(arg instanceof Error){entry.error=this.buildError(arg)}else if(typeof arg==="object"&&arg!==null&&!Array.isArray(arg)){const obj=arg;const redacted=this.redactFieldNames.length>0?redactFields(obj,this.redactFieldNames):obj;Object.assign(attributes,redacted);hasAttributes=true}}if(hasAttributes){entry.attributes=attributes}}buildError(err){const result={type:err.constructor.name,message:err.message};if("code"in err&&typeof err.code==="number"){result.code=String(err.code)}if("errorId"in err&&typeof err.errorId==="string"){result.error_id=err.errorId}if(this.includeStacks&&err.stack){result.stack=err.stack}return result}};StructuredLogTransport=__decorateClass([LogTransport({name:"StructuredLogTransport",description:"Produces structured log objects and forwards to configurable sinks"})],StructuredLogTransport);var OTEL_TRACER=Symbol.for("frontmcp:observability:otel-tracer");var OTEL_CONFIG=Symbol.for("frontmcp:observability:otel-config");function isRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function jsonBytes(value){try{return new TextEncoder().encode(JSON.stringify(value)??"").length}catch{return void 0}}function contentTypeOf(item){if(!isRecord(item))return void 0;const{type,mimeType,text,blob}=item;if(typeof mimeType==="string")return mimeType;if(typeof type==="string")return type;if(text!==void 0)return"text";return blob!==void 0?"blob":void 0}function contentItemsOf(result){if(Array.isArray(result["content"]))return result["content"];if(Array.isArray(result["contents"]))return result["contents"];if(Array.isArray(result["messages"]))return result["messages"].map(message=>message?.content);return[]}function summarizeInput(args){return{bytes:jsonBytes(args??{}),keys:isRecord(args)?Object.keys(args):[]}}function summarizeOutput(result){const summary={bytes:jsonBytes(result)};if(!isRecord(result))return summary;const contentTypes=contentItemsOf(result).map(contentTypeOf).filter(type=>type!==void 0);summary.content_types=[...new Set(contentTypes)];if(isRecord(result["structuredContent"]))summary.keys=Object.keys(result["structuredContent"]);if(Array.isArray(result["content"]))summary.is_error=result["isError"]===true;return summary}var RequestLogCollector=class{constructor(context,options){this.entries=[];this.hooksTriggered=new Set;this.authenticated=false;this.status="ok";this.finalized=false;this.requestId=context.requestId;this.traceId=context.traceId;this.sessionIdHash=context.sessionIdHash;this.scopeId=context.scopeId;this.startTime=new Date;this.maxEntries=options?.maxEntries??500;this.includeSummaries=options?.includeSummaries===true;this.onComplete=options?.onRequestComplete}addEntry(entry){if(this.finalized||this.entries.length>=this.maxEntries)return;const logEntry={timestamp:entry.timestamp,level:entry.level,message:entry.message};if(entry.flow_name){logEntry.stage=entry.flow_name}if(entry.elapsed_ms!==void 0){logEntry.elapsed_ms=entry.elapsed_ms}if(entry.attributes&&Object.keys(entry.attributes).length>0){logEntry.attributes=entry.attributes}this.entries.push(logEntry)}addHook(stage){this.hooksTriggered.add(stage)}setHttpInfo(method,path){this.httpMethod=method;this.httpPath=path}setRpcMethod(method){this.rpcMethod=method}setToolName(name){this.toolName=name}setResourceUri(uri){this.resourceUri=uri}setPromptName(name){this.promptName=name}setInput(args){if(this.includeSummaries)this.inputSummary=summarizeInput(args)}setOutput(result){if(this.includeSummaries&&result!==void 0)this.outputSummary=summarizeOutput(result)}setAuthInfo(type,authenticated){this.authType=type;this.authenticated=authenticated}setStatus(status,statusCode){this.status=status;this.statusCode=statusCode}setStatusCode(statusCode){this.statusCode=statusCode;if(statusCode>=400)this.status="error"}setError(error){this.error=error;this.status="error"}async finalize(){if(this.finalized){return this.finalizedLog}this.finalized=true;const log=this.toRequestLog();this.finalizedLog=log;if(this.onComplete){try{await this.onComplete(log)}catch{}}return log}toRequestLog(){const endTime=new Date;return{request_id:this.requestId,trace_id:this.traceId,session_id_hash:this.sessionIdHash,scope_id:this.scopeId,start_time:this.startTime.toISOString(),end_time:endTime.toISOString(),duration_ms:endTime.getTime()-this.startTime.getTime(),http_method:this.httpMethod,http_path:this.httpPath,rpc_method:this.rpcMethod,tool_name:this.toolName,resource_uri:this.resourceUri,prompt_name:this.promptName,auth_type:this.authType,authenticated:this.authenticated,status:this.status,status_code:this.statusCode,error:this.error,hooks_triggered:Array.from(this.hooksTriggered),entries:[...this.entries],...this.inputSummary&&{input_summary:this.inputSummary},...this.outputSummary&&{output_summary:this.outputSummary}}}isFinalized(){return this.finalized}getEntryCount(){return this.entries.length}};import{isAnonymousSubject as isAnonymousSubject2}from"@frontmcp/sdk";import{context as otelContext3,SpanKind as SpanKind12,SpanStatusCode as SpanStatusCode2,trace as trace3}from"@opentelemetry/api";import{addHookObserver,FlowControl,InternalMcpError,isAnonymousSubject,toMcpError}from"@frontmcp/sdk";import{sha256Hex}from"@frontmcp/utils";var McpAttributes={METHOD_NAME:"mcp.method.name",SESSION_ID:"mcp.session.id",RESOURCE_URI:"mcp.resource.uri",COMPONENT_TYPE:"mcp.component.type",COMPONENT_KEY:"mcp.component.key"};var FrontMcpAttributes={SCOPE_ID:"frontmcp.scope.id",SERVER_NAME:"frontmcp.server.name",TOOL_NAME:"frontmcp.tool.name",TOOL_OWNER:"frontmcp.tool.owner",RESOURCE_URI:"frontmcp.resource.uri",RESOURCE_NAME:"frontmcp.resource.name",PROMPT_NAME:"frontmcp.prompt.name",FLOW_NAME:"frontmcp.flow.name",FLOW_STAGE:"frontmcp.flow.stage",HOOK_STAGE:"frontmcp.hook.stage",HOOK_OWNER:"frontmcp.hook.owner",SESSION_ID_HASH:"frontmcp.session.id_hash",AUTH_TYPE:"frontmcp.auth.type",REQUEST_ID:"frontmcp.request.id",PROVIDER_TYPE:"frontmcp.provider.type",DELEGATE_ORIGINAL_NAME:"frontmcp.delegate.original_name",TRANSPORT_TYPE:"frontmcp.transport.type",TRANSPORT_REQUEST_TYPE:"frontmcp.transport.request_type",SESSION_PROTOCOL:"frontmcp.session.protocol",SESSION_CREATED:"frontmcp.session.created",AUTH_MODE:"frontmcp.auth.mode",AUTH_RESULT:"frontmcp.auth.result",OAUTH_GRANT_TYPE:"frontmcp.oauth.grant_type",ELICITATION_ID:"frontmcp.elicitation.id",AGENT_NAME:"frontmcp.agent.name",AGENT_ITERATIONS:"frontmcp.agent.iterations",AGENT_EXECUTION_DURATION_MS:"frontmcp.agent.execution_duration_ms",STARTUP_TOOLS_COUNT:"frontmcp.startup.tools_count",STARTUP_RESOURCES_COUNT:"frontmcp.startup.resources_count",STARTUP_PROMPTS_COUNT:"frontmcp.startup.prompts_count",STARTUP_PLUGINS_COUNT:"frontmcp.startup.plugins_count",STARTUP_DURATION_MS:"frontmcp.startup.duration_ms"};var HttpAttributes={METHOD:"http.request.method",STATUS_CODE:"http.response.status_code",URL_PATH:"url.path",URL_FULL:"url.full",URL_SCHEME:"url.scheme",SERVER_ADDRESS:"server.address",SERVER_PORT:"server.port"};var RpcAttributes={SYSTEM:"rpc.system",SERVICE:"rpc.service",METHOD:"rpc.method",JSONRPC_VERSION:"rpc.jsonrpc.version",JSONRPC_REQUEST_ID:"rpc.jsonrpc.request_id"};var EnduserAttributes={ID:"enduser.id",SCOPE:"enduser.scope"};import{SpanKind as SpanKind2}from"@opentelemetry/api";import{context as otelContext,SpanKind,SpanStatusCode,trace}from"@opentelemetry/api";function startSpan(tracer,options){const parentCtx=options.parentContext??otelContext.active();const span=tracer.startSpan(options.name,{kind:options.kind??SpanKind.INTERNAL,attributes:options.attributes},parentCtx);const spanContext=trace.setSpan(parentCtx,span);return{span,context:spanContext}}function endSpanOk(span){span.setStatus({code:SpanStatusCode.OK});span.end()}function endSpanError(span,error){const message=typeof error==="string"?error:error.message;span.setStatus({code:SpanStatusCode.ERROR,message});if(error instanceof Error){span.recordException(error)}span.end()}async function withSpan(tracer,options,fn){const{span,context:spanContext}=startSpan(tracer,options);return otelContext.with(spanContext,async()=>{try{const result=await fn(span);endSpanOk(span);return result}catch(err){endSpanError(span,err instanceof Error?err:String(err));throw err}})}function startAuthSpan(tracer,options){return startSpan(tracer,{name:`auth ${options.flowName}`,kind:SpanKind2.INTERNAL,attributes:{[FrontMcpAttributes.FLOW_NAME]:options.flowName},parentContext:options.parentContext})}function setAuthMode(span,mode){span.setAttribute(FrontMcpAttributes.AUTH_MODE,mode)}function setAuthResult(span,result){span.setAttribute(FrontMcpAttributes.AUTH_RESULT,result)}import{SpanKind as SpanKind3}from"@opentelemetry/api";function startFetchSpan(tracer,options){return startSpan(tracer,{name:options.method.toUpperCase(),kind:SpanKind3.CLIENT,attributes:{[HttpAttributes.METHOD]:options.method.toUpperCase(),[HttpAttributes.URL_FULL]:options.url},parentContext:options.parentContext})}function setFetchResponseStatus(span,statusCode){span.setAttribute(HttpAttributes.STATUS_CODE,statusCode)}import{SpanKind as SpanKind4}from"@opentelemetry/api";function recordHookEvent(parentSpan,stage,owner){const attributes={};if(owner){attributes[FrontMcpAttributes.HOOK_OWNER]=owner}parentSpan.addEvent(`hook.${stage}`,attributes)}function startHookSpan(tracer,options){const attributes={[FrontMcpAttributes.HOOK_STAGE]:options.stage};if(options.owner){attributes[FrontMcpAttributes.HOOK_OWNER]=options.owner}if(options.flowName){attributes[FrontMcpAttributes.FLOW_NAME]=options.flowName}return startSpan(tracer,{name:`hook ${options.stage}`,kind:SpanKind4.INTERNAL,attributes,parentContext:options.parentContext})}import{SpanKind as SpanKind5}from"@opentelemetry/api";function startHttpServerSpan(tracer,options){const attributes={[HttpAttributes.METHOD]:options.method.toUpperCase(),[HttpAttributes.URL_PATH]:options.path};if(options.scheme){attributes[HttpAttributes.URL_SCHEME]=options.scheme}if(options.serverAddress){attributes[HttpAttributes.SERVER_ADDRESS]=options.serverAddress}if(options.serverPort){attributes[HttpAttributes.SERVER_PORT]=options.serverPort}if(options.scopeId){attributes[FrontMcpAttributes.SCOPE_ID]=options.scopeId}if(options.requestId){attributes[FrontMcpAttributes.REQUEST_ID]=options.requestId}return startSpan(tracer,{name:`${options.method.toUpperCase()} ${options.path}`,kind:SpanKind5.SERVER,attributes,parentContext:options.parentContext})}function setHttpResponseStatus(span,statusCode){span.setAttribute(HttpAttributes.STATUS_CODE,statusCode)}import{SpanKind as SpanKind6}from"@opentelemetry/api";function startPromptSpan(tracer,options){return startSpan(tracer,{name:`prompt ${options.name}`,kind:SpanKind6.INTERNAL,attributes:{[FrontMcpAttributes.PROMPT_NAME]:options.name,[McpAttributes.COMPONENT_TYPE]:"prompt",[McpAttributes.COMPONENT_KEY]:`prompt:${options.name}`},parentContext:options.parentContext})}import{SpanKind as SpanKind7}from"@opentelemetry/api";function startResourceSpan(tracer,options){const attributes={[FrontMcpAttributes.RESOURCE_URI]:options.uri,[McpAttributes.RESOURCE_URI]:options.uri,[McpAttributes.COMPONENT_TYPE]:"resource",[McpAttributes.COMPONENT_KEY]:`resource:${options.uri}`};if(options.name){attributes[FrontMcpAttributes.RESOURCE_NAME]=options.name}return startSpan(tracer,{name:`resource ${options.uri}`,kind:SpanKind7.INTERNAL,attributes,parentContext:options.parentContext})}import{SpanKind as SpanKind8}from"@opentelemetry/api";function startRpcSpan(tracer,options){const attributes={[RpcAttributes.SYSTEM]:"mcp",[RpcAttributes.METHOD]:options.method,[RpcAttributes.JSONRPC_VERSION]:"2.0",[McpAttributes.METHOD_NAME]:options.method};if(options.requestId!==void 0){attributes[RpcAttributes.JSONRPC_REQUEST_ID]=String(options.requestId)}if(options.scopeId){attributes[FrontMcpAttributes.SCOPE_ID]=options.scopeId}if(options.serviceName){attributes[RpcAttributes.SERVICE]=options.serviceName;attributes[FrontMcpAttributes.SERVER_NAME]=options.serviceName}if(options.sessionIdHash){attributes[McpAttributes.SESSION_ID]=options.sessionIdHash;attributes[FrontMcpAttributes.SESSION_ID_HASH]=options.sessionIdHash}return startSpan(tracer,{name:options.method,kind:SpanKind8.SERVER,attributes,parentContext:options.parentContext})}import{SpanKind as SpanKind9}from"@opentelemetry/api";function emitStartupReport(tracer,data){const attributes={[FrontMcpAttributes.STARTUP_TOOLS_COUNT]:data.toolsCount,[FrontMcpAttributes.STARTUP_RESOURCES_COUNT]:data.resourcesCount,[FrontMcpAttributes.STARTUP_PROMPTS_COUNT]:data.promptsCount,[FrontMcpAttributes.STARTUP_PLUGINS_COUNT]:data.pluginsCount,[FrontMcpAttributes.STARTUP_DURATION_MS]:data.durationMs};if(data.scopeId){attributes[FrontMcpAttributes.SCOPE_ID]=data.scopeId}const{span}=startSpan(tracer,{name:"frontmcp.startup",kind:SpanKind9.INTERNAL,attributes});endSpanOk(span)}import{SpanKind as SpanKind10}from"@opentelemetry/api";function startToolSpan(tracer,options){const attributes={[FrontMcpAttributes.TOOL_NAME]:options.name,[McpAttributes.COMPONENT_TYPE]:"tool",[McpAttributes.COMPONENT_KEY]:`tool:${options.name}`};if(options.owner){attributes[FrontMcpAttributes.TOOL_OWNER]=options.owner}if(options.enduserId){attributes[EnduserAttributes.ID]=options.enduserId}if(options.enduserScope){attributes[EnduserAttributes.SCOPE]=options.enduserScope}return startSpan(tracer,{name:`tool ${options.name}`,kind:SpanKind10.INTERNAL,attributes,parentContext:options.parentContext})}import{SpanKind as SpanKind11}from"@opentelemetry/api";function startTransportSpan(tracer,options){const attributes={[FrontMcpAttributes.TRANSPORT_TYPE]:options.type};if(options.sessionIdHash){attributes[FrontMcpAttributes.SESSION_ID_HASH]=options.sessionIdHash}if(options.sessionCreated!==void 0){attributes[FrontMcpAttributes.SESSION_CREATED]=options.sessionCreated}return startSpan(tracer,{name:`transport ${options.type}`,kind:SpanKind11.INTERNAL,attributes,parentContext:options.parentContext})}function setTransportRequestType(span,requestType){span.setAttribute(FrontMcpAttributes.TRANSPORT_REQUEST_TYPE,requestType)}import{context as otelContext2,trace as trace2,TraceFlags}from"@opentelemetry/api";function frontmcpToOTelSpanContext(tc){return{traceId:tc.traceId,spanId:tc.parentId,traceFlags:tc.traceFlags&TraceFlags.SAMPLED?TraceFlags.SAMPLED:TraceFlags.NONE,isRemote:true}}function otelToFrontmcpContext(sc){const flags=sc.traceFlags.toString(16).padStart(2,"0");return{traceId:sc.traceId,parentId:sc.spanId,traceFlags:sc.traceFlags,raw:`00-${sc.traceId}-${sc.spanId}-${flags}`}}function createOTelContextFromTrace(tc){const spanContext=frontmcpToOTelSpanContext(tc);const span=trace2.wrapSpanContext(spanContext);return trace2.setSpan(otelContext2.active(),span)}var SPAN_KEY=Symbol.for("frontmcp:otel:span");var SPAN_CTX_KEY=Symbol.for("frontmcp:otel:span-ctx");var EXEC_SPAN_KEY=Symbol.for("frontmcp:otel:exec-span");var ACTIVE_SPAN_KEY=Symbol.for("frontmcp:otel:active-span");var ACTIVE_OTEL_CTX_KEY=Symbol.for("frontmcp:otel:active-otel-ctx");var STAGE_TS_KEY=Symbol.for("frontmcp:otel:stage-ts");var STAGE_EVENTS_KEY=Symbol.for("frontmcp:otel:stage-events");var HTTP_SPAN_CTX_KEY=Symbol.for("frontmcp:otel:http-span-ctx");function sessionTracingId(sessionId){return sha256Hex(sessionId).slice(0,16)}function getTracer(){return trace3.getTracer("@frontmcp/observability")}function extractContext(flowCtx){try{const ctx=flowCtx.get?.(Symbol.for("frontmcp:CONTEXT"));if(ctx)return ctx}catch{}return flowCtx.state?.ctx??flowCtx.state?.frontmcpContext}function storeActiveSpan(flowCtx,span,otelCtx){try{const ctx=flowCtx.get?.(Symbol.for("frontmcp:CONTEXT"));if(ctx&&typeof ctx.set==="function"){ctx.set(ACTIVE_SPAN_KEY,span);ctx.set(ACTIVE_OTEL_CTX_KEY,otelCtx)}}catch{}}function clearActiveSpan(flowCtx){try{const ctx=flowCtx.get?.(Symbol.for("frontmcp:CONTEXT"));if(ctx&&typeof ctx.delete==="function"){ctx.delete(ACTIVE_SPAN_KEY);ctx.delete(ACTIVE_OTEL_CTX_KEY)}}catch{}}function beginFlowSpan(flowCtx,options,span,spanCtx){flowCtx.state[SPAN_KEY]=span;flowCtx.state[SPAN_CTX_KEY]=spanCtx;flowCtx.state[STAGE_TS_KEY]=Date.now();flowCtx.state[STAGE_EVENTS_KEY]=options.flowStageEvents!==false}function parentContextOf(ctx){return ctx.get?.(HTTP_SPAN_CTX_KEY)??createOTelContextFromTrace(ctx.traceContext)}function flowFailureOf(flowError){const failed=flowError?.originalError;const error=flowError instanceof FlowControl?failed instanceof Error?failed:new InternalMcpError(`Flow ended with: ${flowError.type}`):flowError instanceof Error?flowError:new Error(String(flowError));const reported=toMcpError(error);return{error,type:reported.name,message:reported.getPublicMessage(),code:reported.code,errorId:reported.errorId}}function endFailedSpan(span,flowError){const failure=flowFailureOf(flowError);span.setStatus({code:SpanStatusCode2.ERROR,message:failure.message});span.recordException({name:failure.type,message:failure.message,code:failure.code,stack:failure.error.stack});span.end()}function traceparentOf(span){const{traceId,spanId,traceFlags}=span.spanContext();return`00-${traceId}-${spanId}-${traceFlags.toString(16).padStart(2,"0")}`}function recordStageEvent(span,stageName,state){if(state[STAGE_EVENTS_KEY]===false)return;const now=Date.now();const prev=state[STAGE_TS_KEY];const attributes={};if(prev){attributes["duration_ms"]=now-prev}state[STAGE_TS_KEY]=now;span.addEvent(`stage.${stageName}`,attributes)}function onHttpWillTrace(options,flowCtx){if(options.httpSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=createOTelContextFromTrace(ctx.traceContext);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startHttpServerSpan(tracer,{method:ctx.metadata?.customHeaders?.["x-http-method"]??"POST",path:ctx.metadata?.customHeaders?.["x-url-path"]??"/",scopeId:ctx.scopeId,requestId:ctx.requestId,parentContext:parentOTelCtx});span.setAttribute(McpAttributes.SESSION_ID,sessionHash);span.setAttribute(FrontMcpAttributes.SESSION_ID_HASH,sessionHash);ctx.set?.(HTTP_SPAN_CTX_KEY,spanCtx);beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"traceRequest",flowCtx.state)}function onHttpWillAcquireQuota(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"acquireQuota",flowCtx.state)}function onHttpDidAcquireQuota(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"acquireQuota.done",flowCtx.state)}function onHttpWillCheckAuth(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"checkAuthorization",flowCtx.state)}function onHttpDidCheckAuth(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"checkAuthorization.done",flowCtx.state)}function onHttpWillRoute(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"router",flowCtx.state)}function onHttpDidRoute(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"router.done",flowCtx.state)}function onHttpDidFinalize(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"finalize",flowCtx.state);const statusCode=flowCtx.state?.statusCode??200;setHttpResponseStatus(span,statusCode);if(statusCode>=400){endSpanError(span,`HTTP ${statusCode}`)}else{endSpanOk(span)}}function onToolWillParse(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startRpcSpan(tracer,{method:"tools/call",scopeId:ctx.scopeId,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onToolWillFindTool(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"findTool",flowCtx.state)}function onToolWillCheckAuth(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"checkToolAuthorization",flowCtx.state)}function onEntryWillCheckAuthorities(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"checkEntryAuthorities",flowCtx.state)}function onEntryDidCheckAuthorities(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"checkEntryAuthorities.done",flowCtx.state);span.setAttribute("auth.authorities.result","granted")}function onToolWillCreateContext(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"createToolCallContext",flowCtx.state)}function onToolWillValidateInput(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"validateInput",flowCtx.state)}function onToolWillExecute(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);const rpcCtx=flowCtx.state?.[SPAN_CTX_KEY];const tracer=getTracer();const toolName=flowCtx.state?.input?.name??"unknown";const toolOwner=flowCtx.state?._toolOwnerId;const enduser=ctx?.authInfo;const{span:toolSpan,context:toolOTelCtx}=startToolSpan(tracer,{name:toolName,owner:toolOwner,enduserId:enduser?.clientId??enduser?.extra?.sub,enduserScope:Array.isArray(enduser?.scopes)?enduser.scopes.join(" "):void 0,parentContext:rpcCtx});flowCtx.state[EXEC_SPAN_KEY]=toolSpan;flowCtx.state[STAGE_TS_KEY]=Date.now();recordStageEvent(toolSpan,"execute.start",flowCtx.state);storeActiveSpan(flowCtx,toolSpan,toolOTelCtx)}function onToolDidExecute(options,flowCtx){const toolSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!toolSpan)return;recordStageEvent(toolSpan,"execute.done",flowCtx.state);endSpanOk(toolSpan);flowCtx.state[EXEC_SPAN_KEY]=void 0;clearActiveSpan(flowCtx)}function onToolWillValidateOutput(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"validateOutput",flowCtx.state)}function onToolWillApplyUI(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"applyUI",flowCtx.state)}function onToolDidFinalize(flowCtx){const rpcSpan=flowCtx.state?.[SPAN_KEY];const toolSpan=flowCtx.state?.[EXEC_SPAN_KEY];const error=flowCtx.state?.flowError;if(error){if(toolSpan)endFailedSpan(toolSpan,error);if(rpcSpan)endFailedSpan(rpcSpan,error)}else if(rpcSpan){recordStageEvent(rpcSpan,"finalize",flowCtx.state);endSpanOk(rpcSpan)}}function onResourceWillParse(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startRpcSpan(tracer,{method:"resources/read",scopeId:ctx.scopeId,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onResourceWillFind(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"findResource",flowCtx.state)}function onResourceWillExecute(options,flowCtx){if(options.executionSpans===false)return;const rpcCtx=flowCtx.state?.[SPAN_CTX_KEY];const tracer=getTracer();const uri=flowCtx.state?.input?.uri??"unknown";const{span:resSpan,context:resOTelCtx}=startResourceSpan(tracer,{uri,parentContext:rpcCtx});flowCtx.state[EXEC_SPAN_KEY]=resSpan;flowCtx.state[STAGE_TS_KEY]=Date.now();recordStageEvent(resSpan,"execute.start",flowCtx.state);storeActiveSpan(flowCtx,resSpan,resOTelCtx)}function onResourceDidExecute(flowCtx){const resSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!resSpan)return;recordStageEvent(resSpan,"execute.done",flowCtx.state);endSpanOk(resSpan);flowCtx.state[EXEC_SPAN_KEY]=void 0;clearActiveSpan(flowCtx)}function onResourceDidFinalize(flowCtx){const rpcSpan=flowCtx.state?.[SPAN_KEY];const resSpan=flowCtx.state?.[EXEC_SPAN_KEY];const error=flowCtx.state?.flowError;if(error){if(resSpan)endFailedSpan(resSpan,error);if(rpcSpan)endFailedSpan(rpcSpan,error)}else if(rpcSpan){recordStageEvent(rpcSpan,"finalize",flowCtx.state);endSpanOk(rpcSpan)}}function onPromptWillParse(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startRpcSpan(tracer,{method:"prompts/get",scopeId:ctx.scopeId,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onPromptWillFind(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"findPrompt",flowCtx.state)}function onPromptWillExecute(options,flowCtx){if(options.executionSpans===false)return;const rpcCtx=flowCtx.state?.[SPAN_CTX_KEY];const tracer=getTracer();const promptName=flowCtx.state?.input?.name??"unknown";const{span:promptSpan,context:promptOTelCtx}=startPromptSpan(tracer,{name:promptName,parentContext:rpcCtx});flowCtx.state[EXEC_SPAN_KEY]=promptSpan;flowCtx.state[STAGE_TS_KEY]=Date.now();recordStageEvent(promptSpan,"execute.start",flowCtx.state);storeActiveSpan(flowCtx,promptSpan,promptOTelCtx)}function onPromptDidExecute(flowCtx){const promptSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!promptSpan)return;recordStageEvent(promptSpan,"execute.done",flowCtx.state);endSpanOk(promptSpan);flowCtx.state[EXEC_SPAN_KEY]=void 0;clearActiveSpan(flowCtx)}function onPromptDidFinalize(flowCtx){const rpcSpan=flowCtx.state?.[SPAN_KEY];const promptSpan=flowCtx.state?.[EXEC_SPAN_KEY];const error=flowCtx.state?.flowError;if(error){if(promptSpan)endFailedSpan(promptSpan,error);if(rpcSpan)endFailedSpan(rpcSpan,error)}else if(rpcSpan){recordStageEvent(rpcSpan,"finalize",flowCtx.state);endSpanOk(rpcSpan)}}function onAgentWillParse(options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startRpcSpan(tracer,{method:"agents/call",scopeId:ctx.scopeId,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onAgentWillFind(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,"findAgent",flowCtx.state)}function onAgentWillExecute(options,flowCtx){if(options.executionSpans===false)return;const rpcCtx=flowCtx.state?.[SPAN_CTX_KEY];const tracer=getTracer();const agentName=flowCtx.state?.input?.name??"unknown";const{span:agentSpan}=startSpan(tracer,{name:`agent ${agentName}`,kind:SpanKind12.INTERNAL,attributes:{[FrontMcpAttributes.FLOW_NAME]:"agents:call-agent",[McpAttributes.COMPONENT_TYPE]:"agent",[McpAttributes.COMPONENT_KEY]:`agent:${agentName}`},parentContext:rpcCtx});const agentOTelCtx=trace3.setSpan(rpcCtx??otelContext3.active(),agentSpan);flowCtx.state[EXEC_SPAN_KEY]=agentSpan;flowCtx.state[STAGE_TS_KEY]=Date.now();recordStageEvent(agentSpan,"execute.start",flowCtx.state);storeActiveSpan(flowCtx,agentSpan,agentOTelCtx)}function onAgentDidExecute(flowCtx){const agentSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!agentSpan)return;recordStageEvent(agentSpan,"execute.done",flowCtx.state);endSpanOk(agentSpan);flowCtx.state[EXEC_SPAN_KEY]=void 0;clearActiveSpan(flowCtx)}function onAgentDidFinalize(flowCtx){const rpcSpan=flowCtx.state?.[SPAN_KEY];const agentSpan=flowCtx.state?.[EXEC_SPAN_KEY];const error=flowCtx.state?.flowError;if(error){if(agentSpan)endFailedSpan(agentSpan,error);if(rpcSpan)endFailedSpan(rpcSpan,error)}else if(rpcSpan){recordStageEvent(rpcSpan,"finalize",flowCtx.state);endSpanOk(rpcSpan)}}function onGenericFlowWillStart(flowName,options,flowCtx){if(options.executionSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startSpan(tracer,{name:flowName,kind:SpanKind12.INTERNAL,attributes:{[FrontMcpAttributes.FLOW_NAME]:flowName,[McpAttributes.SESSION_ID]:sessionHash,[FrontMcpAttributes.SESSION_ID_HASH]:sessionHash,[FrontMcpAttributes.SCOPE_ID]:ctx.scopeId,[FrontMcpAttributes.REQUEST_ID]:ctx.requestId},parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx)}function onGenericFlowStage(stageName,flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,stageName,flowCtx.state)}function onGenericFlowDidFinalize(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;const error=flowCtx.state?.flowError;if(error){endFailedSpan(span,error)}else{endSpanOk(span)}}function onTransportWillStart(transportType,options,flowCtx){if(options.transportSpans===false)return;const ctx=extractContext(flowCtx);if(!ctx)return;const tracer=getTracer();const parentOTelCtx=parentContextOf(ctx);const sessionHash=sessionTracingId(ctx.sessionId);const{span,context:spanCtx}=startTransportSpan(tracer,{type:transportType,sessionIdHash:sessionHash,parentContext:parentOTelCtx});beginFlowSpan(flowCtx,options,span,spanCtx);recordStageEvent(span,"parseInput",flowCtx.state)}function onTransportDidRoute(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"router",flowCtx.state);const requestType=flowCtx.state?.requestType;if(requestType)setTransportRequestType(span,requestType)}function onTransportStage(stageName,flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(span)recordStageEvent(span,stageName,flowCtx.state)}function onTransportDidFinalize(flowCtx){const span=flowCtx.state?.[SPAN_KEY];if(!span)return;recordStageEvent(span,"cleanup",flowCtx.state);const error=flowCtx.state?.flowError;if(error){endFailedSpan(span,error)}else{endSpanOk(span)}}var AUTH_SPAN_KEY=Symbol.for("frontmcp:otel:auth-span");function authResultOf(verifyResult){const kind=verifyResult?.kind??"unauthorized";const sub=verifyResult?.authorization?.user?.sub;if(kind==="authorized"&&(typeof sub!=="string"||isAnonymousSubject(sub)))return"anonymous";return kind}function onHttpWillAuthenticate(options,flowCtx){if(options.authSpans===false||!flowCtx.state)return;const ctx=extractContext(flowCtx);if(!ctx)return;const{span}=startAuthSpan(getTracer(),{flowName:"session:verify",parentContext:parentContextOf(ctx)});flowCtx.state[AUTH_SPAN_KEY]=span}function onHttpDidAuthenticate(flowCtx){const span=flowCtx.state?.[AUTH_SPAN_KEY];if(!span)return;flowCtx.state[AUTH_SPAN_KEY]=void 0;const error=flowCtx.state?.flowError;if(error){setAuthResult(span,"error");endFailedSpan(span,error);return}setAuthResult(span,authResultOf(flowCtx.state?.verifyResult));endSpanOk(span)}function wrapContextFetch(options,flowCtx){const toolCtx=flowCtx.state?.toolContext??flowCtx.state?.toolCallContext;if(!toolCtx||typeof toolCtx.fetch!=="function")return;const originalFetch=toolCtx.fetch.bind(toolCtx);const parentOTelCtx=flowCtx.state?.[SPAN_CTX_KEY];toolCtx.fetch=async(input,init)=>{const fetchSpan=options.fetchSpans===false?void 0:startFetchSpan(getTracer(),{method:init?.method??(input instanceof Request?input.method:"GET"),url:typeof input==="string"?input:input instanceof URL?input.toString():input.url,parentContext:parentOTelCtx}).span;const callingSpan=fetchSpan??flowCtx.state?.[EXEC_SPAN_KEY]??flowCtx.state?.[SPAN_KEY];const headers=new Headers(init?.headers??(input instanceof Request?input.headers:void 0));if(callingSpan&&!headers.has("traceparent"))headers.set("traceparent",traceparentOf(callingSpan));try{const response=await originalFetch(input,{...init,headers});if(fetchSpan){setFetchResponseStatus(fetchSpan,response.status);endSpanOk(fetchSpan)}return response}catch(err){if(fetchSpan)endSpanError(fetchSpan,err instanceof Error?err:String(err));throw err}}}function onAgentDidExecuteEnrich(flowCtx){const agentSpan=flowCtx.state?.[EXEC_SPAN_KEY];if(!agentSpan)return;const meta=flowCtx.state?.executionMeta;if(meta){if(typeof meta.iterations==="number"){agentSpan.setAttribute(FrontMcpAttributes.AGENT_ITERATIONS,meta.iterations)}if(typeof meta.durationMs==="number"){agentSpan.setAttribute(FrontMcpAttributes.AGENT_EXECUTION_DURATION_MS,meta.durationMs)}}}var OBSERVED_KEY=Symbol.for("frontmcp:observability:hook-observer");function installHookObserver(flowCtx,observer){const ctx=extractContext(flowCtx);if(!ctx?.get||!ctx.set||ctx.get(OBSERVED_KEY))return;ctx.set(OBSERVED_KEY,true);addHookObserver({get:key=>ctx.get?.(key),set:(key,value)=>ctx.set?.(key,value)},observer)}async function runInHookSpan(flowCtx,hook,run){const ctx=extractContext(flowCtx);const{span}=startHookSpan(getTracer(),{...hook,parentContext:flowCtx.state?.[SPAN_CTX_KEY]??(ctx&&parentContextOf(ctx))});try{await run();endSpanOk(span)}catch(error){if(error instanceof FlowControl&&error.type!=="fail"&&error.type!=="abort")endSpanOk(span);else endFailedSpan(span,error);throw error}}function reportStartup(data){const tracer=getTracer();emitStartupReport(tracer,data)}var REQUEST_LOG_COLLECTOR=Symbol.for("frontmcp:observability:request-log-collector");var FRONTMCP_CONTEXT=Symbol.for("frontmcp:CONTEXT");function resolve(flowCtx,token){try{return flowCtx.get?.(token)}catch{return void 0}}function currentRequestLog(flowCtx){return resolve(flowCtx,FRONTMCP_CONTEXT)?.get(REQUEST_LOG_COLLECTOR)}function startRequestLog(flowCtx,options){const context=resolve(flowCtx,FRONTMCP_CONTEXT);if(!context)return;const collector=new RequestLogCollector({requestId:context.requestId,traceId:context.traceContext.traceId,sessionIdHash:sessionTracingId(context.sessionId).slice(0,12),scopeId:context.scopeId},options);context.set(REQUEST_LOG_COLLECTOR,collector);const request=flowCtx.rawInput?.request;if(request?.method&&request.path)collector.setHttpInfo(request.method,request.path);const rpcMethod=request?.body?.method;if(typeof rpcMethod==="string")collector.setRpcMethod(rpcMethod)}function recordRequestLogFailure(flowCtx){const flowError=flowCtx.state?.["flowError"];if(!flowError)return;const{type,message,code,errorId}=flowFailureOf(flowError);currentRequestLog(flowCtx)?.setError({type,message,code,error_id:errorId})}function recordRequestLogOutput(flowCtx){currentRequestLog(flowCtx)?.setOutput(flowCtx.state?.["output"])}function recordRequestLogAuth(flowCtx){const verifyResult=flowCtx.state?.["verifyResult"];const authorization=flowCtx.rawInput?.request?.headers?.["authorization"];const scheme=typeof authorization==="string"?authorization.trim().split(/\s+/)[0].toLowerCase():"";const sub=verifyResult?.authorization?.user?.sub;const anonymous=typeof sub!=="string"||isAnonymousSubject2(sub);currentRequestLog(flowCtx)?.setAuthInfo(anonymous||!scheme?"anonymous":scheme,verifyResult?.kind==="authorized"&&!anonymous)}async function completeRequestLog(flowCtx){const collector=currentRequestLog(flowCtx);if(!collector||collector.isFinalized())return;const statusCode=flowCtx.state?.["statusCode"]??flowCtx.rawInput?.response?.statusCode;if(typeof statusCode==="number")collector.setStatusCode(statusCode);await collector.finalize()}import{FlowHooksOf,ResourceHook,ToolHook}from"@frontmcp/sdk";import{appendFile,dirname,ensureDir}from"@frontmcp/utils";var DEV_EVENTS_IPC_MESSAGE="dev-events";var JsonlFileSink=class{constructor(path){this.path=path;this.name="file"}async write(events){this.folderReady??=ensureDir(dirname(this.path));await this.folderReady;await appendFile(this.path,events.map(event=>`${JSON.stringify(event)}
5
+ `).join(""))}};var IpcDevEventSink=class{constructor(){this.name="ipc"}write(events){const send=process.send;if(typeof send!=="function"||!process.connected)throw new Error("no IPC channel to the dev parent");return new Promise((resolve2,reject)=>{send.call(process,{__frontmcp:DEV_EVENTS_IPC_MESSAGE,events},error=>error?reject(error):resolve2())})}};var DevEventStream=class{constructor(sinks,options){this.sinks=sinks;this.options=options;this.queue=[];this.closed=false;this.warnedFull=false;this.failedSinks=new Set}emit(event){if(this.closed)return;if(this.queue.length>=this.options.maxQueue){if(!this.warnedFull){this.warnedFull=true;this.options.logger.warn(`Dev events: the queue of ${this.options.maxQueue} events is full; new events are dropped until the sinks catch up`)}return}this.queue.push(event);this.draining??=this.drain()}flush(){return this.draining??Promise.resolve()}async onShutdown(){while(this.draining)await this.draining;this.closed=true;await Promise.all(this.sinks.map(sink=>this.attempt(sink,()=>sink.close?.())))}async drain(){await Promise.resolve();while(this.queue.length>0){const batch=this.queue;this.queue=[];await Promise.all(this.sinks.map(sink=>this.attempt(sink,()=>sink.write(batch))))}this.draining=void 0}async attempt(sink,run){try{await run()}catch(error){if(this.failedSinks.has(sink))return;this.failedSinks.add(sink);const reason=error instanceof Error?error.message:String(error);this.options.logger.warn(`Dev events: the ${sink.name??"custom"} sink failed (${reason}); its later failures are not logged`)}}};import{metrics}from"@opentelemetry/api";function snapshotKey(name,attributes){const keys=Object.keys(attributes).sort();if(keys.length===0)return name;const tail=keys.map(k=>`${k}=${attributes[k]}`).join(",");return`${name}{${tail}}`}var snapshotStore=new Map;var TelemetryCounterImpl=class{constructor(name,otelCounter){this.name=name;this.otelCounter=otelCounter}inc(by=1,attributes={}){if(!Number.isFinite(by)||by<0){return}try{this.otelCounter.add(by,attributes)}catch{}const key=snapshotKey(this.name,attributes);const existing=snapshotStore.get(key);if(existing){existing.count+=by}else{snapshotStore.set(key,{name:this.name,count:by,attributes:{...attributes}})}}};var METER_NAME="@frontmcp/observability";var counterCache=new Map;function createCounter(name,description){const existing=counterCache.get(name);if(existing)return existing;const meter=metrics.getMeter(METER_NAME);const otelCounter=meter.createCounter(name,description?{description}:void 0);const counter=new TelemetryCounterImpl(name,otelCounter);counterCache.set(name,counter);return counter}function getMetricSnapshot(){return Array.from(snapshotStore.values()).map(entry=>({name:entry.name,count:entry.count,attributes:{...entry.attributes}}))}function getCounterTotal(name){let sum=0;for(const entry of snapshotStore.values()){if(entry.name===name)sum+=entry.count}return sum}function resetMetricSnapshot(){snapshotStore.clear()}function resetTelemetrySnapshotForTesting(){snapshotStore.clear()}function resetCounterCacheForTesting(){counterCache.clear()}var KNOWN_BUNDLE_SOURCES=["static","npm","saas-pull","webhook","filesystem","unknown"];function normalizeBundleSource(value){if(typeof value!=="string")return"unknown";return KNOWN_BUNDLE_SOURCES.includes(value)?value:"unknown"}var KNOWN_ERROR_REASONS=["network","timeout","invalid_response","parse_error","unknown"];function normalizeErrorReason(err){if(!err)return"unknown";const name=err instanceof Error?err.name:"";const message=err instanceof Error?err.message:typeof err==="string"?err:"";const haystack=`${name} ${message}`.toLowerCase();if(name==="TimeoutError"||haystack.includes("timeout")||haystack.includes("timed out")){return"timeout"}if(name==="NetworkError"||name==="FetchError"||haystack.includes("network")||haystack.includes("econnrefused")||haystack.includes("econnreset")||haystack.includes("enotfound")||haystack.includes("socket")||haystack.includes("dns")){return"network"}if(name==="SyntaxError"||haystack.includes("parse")||haystack.includes("json")){return"parse_error"}if(name==="TypeError"||name==="RangeError"||haystack.includes("invalid")||haystack.includes("malformed")||haystack.includes("schema")){return"invalid_response"}return"unknown"}var InFlightCalls=class{constructor(now){this.now=now;this.records=new Set}async track(call,body,stillRunning=()=>void 0){const record={...call,startedAt:this.now()};this.records.add(record);const end=()=>{record.endedAt??=this.now()};try{await body()}finally{const execution=stillRunning();if(execution instanceof Promise)execution.then(end,end);else end()}}running(){return[...this.records].filter(record=>record.endedAt===void 0).map(record=>({...record}))}during(from,to){return[...this.records].filter(record=>record.startedAt<=to&&(record.endedAt??to)>=from).map(record=>({...record}))}prune(time){for(const record of this.records){if(record.endedAt!==void 0&&record.endedAt<time)this.records.delete(record)}}};var SAMPLE_INTERVAL_MS=10;function observeGcPauses(record){let perfHooks;try{perfHooks=__require("node:perf_hooks")}catch{return void 0}try{const observer=new perfHooks.PerformanceObserver(list=>{for(const entry of list.getEntries())record({startTime:entry.startTime,duration:entry.duration})});observer.observe({entryTypes:["gc"]});return()=>observer.disconnect()}catch{return()=>void 0}}function overlapMs(pause,stall){return Math.max(0,Math.min(pause.startTime+pause.duration,stall.to)-Math.max(pause.startTime,stall.from))}var StallDetector=class{constructor(options){this.pending=[];this.gcPauses=[];this.previousSampleAt=0;this.thresholdMs=options.thresholdMs;this.onStall=options.onStall;this.now=options.now??(()=>performance.now());this.observeGc=options.observeGc??observeGcPauses;this.calls=new InFlightCalls(this.now)}get running(){return this.timer!==void 0}start(){if(this.timer)return;this.stopObservingGc=this.observeGc(pause=>this.gcPauses.push(pause));if(!this.stopObservingGc)return;this.previousSampleAt=this.now();this.timer=setInterval(()=>this.sample(),SAMPLE_INTERVAL_MS);this.timer.unref?.()}stop(){clearInterval(this.timer);this.timer=void 0;this.reportPending();this.stopObservingGc?.();this.stopObservingGc=void 0}sample(){if(!this.timer)return;const now=this.now();this.reportPending();const from=this.previousSampleAt;const stallMs=now-from;if(stallMs>=this.thresholdMs)this.pending.push({from,to:now,stallMs,calls:this.calls.during(from,now)});this.calls.prune(now);const keepFrom=Math.min(now,...this.pending.map(stall=>stall.from));this.gcPauses=this.gcPauses.filter(pause=>pause.startTime+pause.duration>=keepFrom);this.previousSampleAt=now}reportPending(){for(const stall of this.pending.splice(0)){try{this.onStall(this.reportOf(stall))}catch{}}}reportOf(stall){const gcTotal=this.gcPauses.reduce((sum,pause)=>sum+overlapMs(pause,stall),0);const gcMs=Math.min(stall.stallMs,gcTotal);const cause=stall.stallMs-gcMs<this.thresholdMs?"gc":stall.calls.length>0?"calls":"unknown";return{stallMs:Math.round(stall.stallMs),gcMs:Math.round(gcMs),cause,calls:stall.calls.map(({method,entry,session,startedAt,endedAt})=>({method,entry,...session?{session}:{},runningMs:Math.round(Math.min(endedAt??stall.to,stall.to)-startedAt)}))}}};var STALL_SECONDS_COUNTER="frontmcp_event_loop_stall_seconds_total";var STALL_SECONDS_DESCRIPTION="Seconds the event loop was stalled, by the method and entry of each call in flight, or gc, or unknown";var MAX_NAMED_CALLS=5;function describeCall(call){const session=call.session?`, session ${call.session}`:"";return`${call.method} ${call.entry} (${call.runningMs} ms${session})`}function describeStall(report){const head=`Event loop stalled for ${report.stallMs} ms`;if(report.cause==="gc")return`${head}, ${report.gcMs} ms of it in garbage collection`;const gc=report.gcMs>0?` (${report.gcMs} ms in garbage collection)`:"";if(report.calls.length===0)return`${head}${gc} with no call in flight`;const named=report.calls.slice(0,MAX_NAMED_CALLS).map(describeCall).join(", ");const more=report.calls.length>MAX_NAMED_CALLS?` and ${report.calls.length-MAX_NAMED_CALLS} more`:"";return`${head}${gc} while running ${named}${more}`}function countStall(report,counter){if(report.gcMs>0)counter.inc(report.gcMs/1e3,{cause:"gc",entry:""});if(report.cause==="gc")return;const seconds=(report.stallMs-report.gcMs)/1e3;if(report.calls.length===0){counter.inc(seconds,{cause:"unknown",entry:""});return}const entries=new Map(report.calls.map(call=>[`${call.method} ${call.entry}`,call]));for(const call of entries.values())counter.inc(seconds,{cause:call.method,entry:call.entry})}var PromptHook=FlowHooksOf("prompts:get-prompt");function resolvedEntryOf(flow,method){if(method==="tools/call")return flow.state?.tool?.fullName;if(method==="resources/read")return flow.state?.resource?.fullName;return flow.state?.prompt?.fullName}function reportedEntryOf(flow,method){const requested=method==="tools/call"?flow.toolName:method==="prompts/get"?flow.promptName:void 0;return resolvedEntryOf(flow,method)??requested??""}function sessionOf(flow){const sessionId=flow.request?.sessionId;return sessionId?{session:sessionTracingId(sessionId).slice(0,12)}:{}}function sinksOf(options){return[...options.file?[new JsonlFileSink(options.file)]:[],...options.ipc?[new IpcDevEventSink]:[],...options.sinks]}var _CallMonitor=class _CallMonitor{constructor(stallOptions,devEventsOptions,logger){this.logger=logger;this.callStarts=new WeakMap;this.devEvents=devEventsOptions?new DevEventStream(sinksOf(devEventsOptions),{maxQueue:devEventsOptions.maxQueue,logger}):void 0;if(!stallOptions)return;this.stallCounter=createCounter(STALL_SECONDS_COUNTER,STALL_SECONDS_DESCRIPTION);this.sharedStalls=_CallMonitor.sharedDetectorFor(stallOptions.thresholdMs);this.stalls=this.sharedStalls.detector}static{this.sharedDetectors=new Map}static sharedDetectorFor(thresholdMs){const existing=_CallMonitor.sharedDetectors.get(thresholdMs);if(existing)return existing;const monitors=new Set;const detector=new StallDetector({thresholdMs,onStall:report=>{const[reporter]=monitors;reporter?.reportStall(report)}});const shared={detector,monitors};_CallMonitor.sharedDetectors.set(thresholdMs,shared);return shared}onReady(){if(!this.sharedStalls)return;this.sharedStalls.monitors.add(this);this.sharedStalls.detector.start()}async onShutdown(){const shared=this.sharedStalls;if(shared?.monitors.has(this)){if(shared.monitors.size===1)shared.detector.stop();shared.monitors.delete(this)}await this.devEvents?.onShutdown()}markToolCallStart(ctx){this.markStart(ctx)}trackToolExecution(ctx,next){return this.track(ctx,"tools/call",next)}reportToolCall(ctx){this.report(ctx,"tools/call")}markResourceReadStart(ctx){this.markStart(ctx)}trackResourceExecution(ctx,next){return this.track(ctx,"resources/read",next)}reportResourceRead(ctx){this.report(ctx,"resources/read")}markPromptGetStart(ctx){this.markStart(ctx)}trackPromptExecution(ctx,next){return this.track(ctx,"prompts/get",next)}reportPromptGet(ctx){this.report(ctx,"prompts/get")}markStart(ctx){if(this.devEvents&&typeof ctx==="object"&&ctx!==null)this.callStarts.set(ctx,performance.now())}track(ctx,method,next){const flow=ctx;const entry=resolvedEntryOf(flow,method);if(!this.stalls?.running||!entry)return next();return this.stalls.calls.track({method,entry,...sessionOf(flow)},next,()=>flow.state?.abandonedExecution)}reportStall(report){this.logger.warn(describeStall(report));if(this.stallCounter)countStall(report,this.stallCounter);this.devEvents?.emit({type:"stall",at:new Date().toISOString(),...report})}report(ctx,method){if(!this.devEvents||typeof ctx!=="object"||ctx===null)return;const startedAt=this.callStarts.get(ctx);if(startedAt===void 0)return;const flow=ctx;const failure=flow.state?.flowError?flowFailureOf(flow.state.flowError):void 0;this.devEvents.emit({type:"call",at:new Date().toISOString(),method,entry:reportedEntryOf(flow,method),durationMs:Math.round((performance.now()-startedAt)*10)/10,outcome:failure?"error":"ok",...failure?{error:{type:failure.type,code:failure.code}}:{},...sessionOf(flow)})}};__decorateClass([ToolHook.Will("parseInput",{priority:-1e3})],_CallMonitor.prototype,"markToolCallStart",1);__decorateClass([ToolHook.Around("execute",{priority:-1e3})],_CallMonitor.prototype,"trackToolExecution",1);__decorateClass([ToolHook.Finally("finalize",{priority:1e3})],_CallMonitor.prototype,"reportToolCall",1);__decorateClass([ResourceHook.Will("parseInput",{priority:-1e3})],_CallMonitor.prototype,"markResourceReadStart",1);__decorateClass([ResourceHook.Around("execute",{priority:-1e3})],_CallMonitor.prototype,"trackResourceExecution",1);__decorateClass([ResourceHook.Finally("finalize",{priority:1e3})],_CallMonitor.prototype,"reportResourceRead",1);__decorateClass([PromptHook.Will("parseInput",{priority:-1e3})],_CallMonitor.prototype,"markPromptGetStart",1);__decorateClass([PromptHook.Around("execute",{priority:-1e3})],_CallMonitor.prototype,"trackPromptExecution",1);__decorateClass([PromptHook.Finally("finalize",{priority:1e3})],_CallMonitor.prototype,"reportPromptGet",1);var CallMonitor=_CallMonitor;import{SpanKind as SpanKind13,SpanStatusCode as SpanStatusCode3,trace as trace4}from"@opentelemetry/api";var TelemetrySpan=class{constructor(span){this.span=span;this.hasError=false}setAttribute(key,value){this.span.setAttribute(key,value);return this}setAttributes(attrs){this.span.setAttributes(attrs);return this}addEvent(name,attributes){this.span.addEvent(name,attributes);return this}recordError(error){this.span.recordException(error);this.span.setStatus({code:SpanStatusCode3.ERROR,message:error.message});this.hasError=true;return this}end(){if(!this.hasError){this.span.setStatus({code:SpanStatusCode3.OK})}this.span.end()}endWithError(error){const msg=typeof error==="string"?error:error.message;if(error instanceof Error)this.span.recordException(error);this.span.setStatus({code:SpanStatusCode3.ERROR,message:msg});this.span.end()}get raw(){return this.span}};var TelemetryAccessor=class{constructor(ctx){this.ctx=ctx;this.tracer=trace4.getTracer("@frontmcp/observability");this.fallbackContext=createOTelContextFromTrace(ctx.traceContext);this.sessionHash=sessionTracingId(ctx.sessionId);this.baseAttributes={[FrontMcpAttributes.REQUEST_ID]:ctx.requestId,[FrontMcpAttributes.SCOPE_ID]:ctx.scopeId,[McpAttributes.SESSION_ID]:this.sessionHash}}getActiveContext(){const otelCtx=this.ctx.get?.(ACTIVE_OTEL_CTX_KEY);return otelCtx??this.fallbackContext}getActiveSpan(){return this.ctx.get?.(ACTIVE_SPAN_KEY)}startSpan(name,attributes){const span=this.tracer.startSpan(name,{kind:SpanKind13.INTERNAL,attributes:{...this.baseAttributes,...attributes}},this.getActiveContext());return new TelemetrySpan(span)}async withSpan(name,fn,attributes){const telemetrySpan=this.startSpan(name,attributes);try{const result=await fn(telemetrySpan);telemetrySpan.end();return result}catch(err){telemetrySpan.endWithError(err instanceof Error?err:String(err));throw err}}addEvent(name,attributes){const activeSpan=this.getActiveSpan();if(activeSpan){activeSpan.addEvent(name,attributes)}else{const span=this.tracer.startSpan(name,{kind:SpanKind13.INTERNAL,attributes:this.baseAttributes},this.fallbackContext);if(attributes)span.addEvent(name,attributes);span.setStatus({code:SpanStatusCode3.OK});span.end()}}setAttributes(attrs){const activeSpan=this.getActiveSpan();if(activeSpan){activeSpan.setAttributes(attrs)}}createCounter(name,description){return createCounter(name,description)}get traceId(){return trace4.getSpan(this.fallbackContext)?.spanContext().traceId??""}get sessionId(){return this.sessionHash}};import{SpanStatusCode as SpanStatusCode4,trace as trace5}from"@opentelemetry/api";var TelemetryFactory=class{constructor(tracerName="@frontmcp/observability"){this.tracer=trace5.getTracer(tracerName)}createCounter(name,description){return createCounter(name,description)}startSpan(name,attributes,parent){const opts=attributes?{attributes}:void 0;const span=parent?this.tracer.startSpan(name,opts,parent):this.tracer.startSpan(name,opts);return new TelemetrySpan(span)}async withSpan(name,fn,attributes){const span=this.startSpan(name,attributes);try{const result=await fn(span);span.end();return result}catch(err){span.endWithError(err instanceof Error?err:String(err));throw err}}};var TELEMETRY_ACCESSOR=Symbol.for("frontmcp:observability:telemetry-accessor");var TELEMETRY_FACTORY=Symbol.for("frontmcp:observability:telemetry-factory");import{z}from"@frontmcp/sdk";import{InternalMcpError as InternalMcpError2}from"@frontmcp/sdk";var ObservabilityConfigurationError=class extends InternalMcpError2{constructor(message){super(message,"OBSERVABILITY_CONFIGURATION");this.name="ObservabilityConfigurationError"}};var DEV_EVENTS_FILE_ENV="FRONTMCP_DEV_EVENTS_FILE";var DEV_EVENTS_IPC_ENV="FRONTMCP_DEV_EVENTS_IPC";var thresholdMessage={message:"must be a whole number of milliseconds from 20 to 60000"};var maxQueueMessage={message:"must be a whole number from 1 to 100000"};var stallOptionsSchema=z.object({thresholdMs:z.number().int(thresholdMessage).min(20,thresholdMessage).max(6e4,thresholdMessage).default(200)}).strict();var isSink=value=>typeof value==="object"&&value!==null&&typeof value.write==="function";var devEventsOptionsSchema=z.object({file:z.string().min(1,{message:"must be a file path"}).optional(),sinks:z.array(z.custom(isSink,{message:"must be a sink: an object with a write(events) method"})).default([]),maxQueue:z.number().int(maxQueueMessage).min(1,maxQueueMessage).max(1e5,maxQueueMessage).default(1e3)}).strict();function parse(option,schema,input){const result=schema.safeParse(input);if(result.success)return result.data;const problems=result.error.issues.map(issue=>`${[option,...issue.path].join(".")}: ${issue.message}`);throw new ObservabilityConfigurationError(`Invalid ObservabilityPlugin options: ${problems.join("; ")}`)}function resolveStallOptions(input){if(input===void 0||input===false)return false;return parse("stalls",stallOptionsSchema,input===true?{}:input)}function resolveDevEventsOptions(input,env=process.env){if(input===false)return false;const options=parse("devEvents",devEventsOptionsSchema,input===true||input===void 0?{}:input);const envFile=env[DEV_EVENTS_FILE_ENV]||void 0;const ipc=env[DEV_EVENTS_IPC_ENV]==="1";const inDevelopment=envFile!==void 0||ipc||env["NODE_ENV"]==="development";const file=options.file??envFile;if(!inDevelopment||!file&&!ipc&&options.sinks.length===0)return false;return{...file?{file}:{},ipc,sinks:options.sinks,maxQueue:options.maxQueue}}var PromptHook2=FlowHooksOf2("prompts:get-prompt");var ListPromptsHook=FlowHooksOf2("prompts:list-prompts");var SkillSearchHook=FlowHooksOf2("skills:search");var SkillLoadHook=FlowHooksOf2("skills:load");var CompletionHook=FlowHooksOf2("completion:complete");var LegacySseHook=FlowHooksOf2("handle:legacy-sse");var StreamableHttpHook=FlowHooksOf2("handle:streamable-http");var StatelessHttpHook=FlowHooksOf2("handle:stateless-http");var OAuthTokenHook=FlowHooksOf2("oauth:token");var OAuthAuthorizeHook=FlowHooksOf2("oauth:authorize");var OAuthCallbackHook=FlowHooksOf2("oauth:callback");var OAuthProviderCallbackHook=FlowHooksOf2("oauth:provider-callback");var OAuthRegisterHook=FlowHooksOf2("oauth:register");var ElicitRequestHook=FlowHooksOf2("elicitation:request");var ElicitResultHook=FlowHooksOf2("elicitation:result");var SubscribeResourceHook=FlowHooksOf2("resources:subscribe");var UnsubscribeResourceHook=FlowHooksOf2("resources:unsubscribe");var SkillsHttpLlmTxtHook=FlowHooksOf2("skills-http:llm-txt");var SkillsHttpLlmFullTxtHook=FlowHooksOf2("skills-http:llm-full-txt");var SkillsHttpApiHook=FlowHooksOf2("skills-http:api");var WellKnownJwksHook=FlowHooksOf2("well-known.jwks");var WellKnownOAuthServerHook=FlowHooksOf2("well-known.oauth-authorization-server");var WellKnownPrmHook=FlowHooksOf2("well-known.prm");var LoggingSetLevelHook=FlowHooksOf2("logging:set-level");var DEFAULT_TRACING={httpSpans:true,executionSpans:true,hookSpans:false,fetchSpans:true,flowStageEvents:true,transportSpans:true,authSpans:true,oauthSpans:true,elicitationSpans:true,startupReport:true};var ObservabilityPlugin=class extends DynamicPlugin{constructor(options={}){super();this.observeHook=async({flowName,stage,target,flowContext},run)=>{if(target===this)return run();if(this.requestLogsEnabled)currentRequestLog(flowContext)?.addHook(`${flowName}:${stage}`);if(!this.traces("hookSpans"))return run();const owner=target?.constructor?.name;return runInHookSpan(flowContext,{flowName,stage,owner},run)};this.options=resolveOptions(options);this.tracingOpts=this.options.tracing!==false?this.options.tracing:DEFAULT_TRACING}get tracingEnabled(){return this.options.tracing!==false}get requestLogsEnabled(){return this.options.requestLogs!==false}traces(kind){return this.tracingEnabled&&this.tracingOpts[kind]!==false}watchHooks(ctx){if(this.requestLogsEnabled||this.traces("hookSpans"))installHookObserver(ctx,this.observeHook)}annotateRequestLog(ctx,set){if(!this.requestLogsEnabled)return;const flowCtx=ctx;const log=currentRequestLog(ctx);if(log&&flowCtx.state?.input)set(log,flowCtx.state.input)}_httpWillTrace(ctx){if(this.tracingEnabled)onHttpWillTrace(this.tracingOpts,ctx);if(this.options.requestLogs!==false)startRequestLog(ctx,this.options.requestLogs);this.watchHooks(ctx)}_httpWillQuota(ctx){if(this.tracingEnabled)onHttpWillAcquireQuota(ctx)}_httpDidSemaphore(ctx){if(this.tracingEnabled)onHttpDidAcquireQuota(ctx)}_httpWillAuth(ctx){if(!this.tracingEnabled)return;onHttpWillCheckAuth(ctx);onHttpWillAuthenticate(this.tracingOpts,ctx)}_httpDidAuth(ctx){if(this.tracingEnabled)onHttpDidCheckAuth(ctx);if(this.requestLogsEnabled)recordRequestLogAuth(ctx)}_httpFinallyAuth(ctx){if(this.tracingEnabled)onHttpDidAuthenticate(ctx)}_httpWillRoute(ctx){if(this.tracingEnabled)onHttpWillRoute(ctx)}_httpDidRoute(ctx){if(this.tracingEnabled)onHttpDidRoute(ctx)}_httpFinallyFinalize(ctx){if(this.tracingEnabled)onHttpDidFinalize(ctx);if(this.requestLogsEnabled)void completeRequestLog(ctx)}_toolWillParse(ctx){this.watchHooks(ctx);if(this.tracingEnabled)onToolWillParse(this.tracingOpts,ctx)}_toolWillFind(ctx){if(this.tracingEnabled)onToolWillFindTool(ctx);this.annotateRequestLog(ctx,(log,input)=>{log.setToolName(String(input["name"]));log.setInput(input["arguments"])})}_toolWillCheckAuth(ctx){if(this.tracingEnabled)onToolWillCheckAuth(ctx)}_toolWillCheckAuthorities(ctx){if(this.tracingEnabled)onEntryWillCheckAuthorities(ctx)}_toolDidCheckAuthorities(ctx){if(this.tracingEnabled)onEntryDidCheckAuthorities(ctx)}_toolWillCreateCtx(ctx){if(this.tracingEnabled)onToolWillCreateContext(ctx)}_toolWillValidate(ctx){if(this.tracingEnabled)onToolWillValidateInput(ctx)}_toolWillExecute(ctx){if(this.tracingEnabled)onToolWillExecute(this.tracingOpts,ctx)}_toolDidExecute(ctx){if(this.tracingEnabled)onToolDidExecute(this.tracingOpts,ctx)}_toolWillValidateOut(ctx){if(this.tracingEnabled)onToolWillValidateOutput(ctx)}_toolWillApplyUI(ctx){if(this.tracingEnabled)onToolWillApplyUI(ctx)}_toolFinallyFinalize(ctx){if(this.tracingEnabled)onToolDidFinalize(ctx);if(!this.requestLogsEnabled)return;recordRequestLogFailure(ctx);recordRequestLogOutput(ctx)}_resourceWillParse(ctx){this.watchHooks(ctx);if(this.tracingEnabled)onResourceWillParse(this.tracingOpts,ctx)}_resourceWillFind(ctx){if(this.tracingEnabled)onResourceWillFind(ctx);this.annotateRequestLog(ctx,(log,input)=>log.setResourceUri(String(input["uri"])))}_resourceWillCheckAuthorities(ctx){if(this.tracingEnabled)onEntryWillCheckAuthorities(ctx)}_resourceDidCheckAuthorities(ctx){if(this.tracingEnabled)onEntryDidCheckAuthorities(ctx)}_resourceWillExecute(ctx){if(this.tracingEnabled)onResourceWillExecute(this.tracingOpts,ctx)}_resourceDidExecute(ctx){if(this.tracingEnabled)onResourceDidExecute(ctx)}_resourceFinallyFinalize(ctx){if(this.tracingEnabled)onResourceDidFinalize(ctx);if(!this.requestLogsEnabled)return;recordRequestLogFailure(ctx);recordRequestLogOutput(ctx)}_promptWillParse(ctx){this.watchHooks(ctx);if(this.tracingEnabled)onPromptWillParse(this.tracingOpts,ctx)}_promptWillFind(ctx){if(this.tracingEnabled)onPromptWillFind(ctx);this.annotateRequestLog(ctx,(log,input)=>{log.setPromptName(String(input["name"]));log.setInput(input["arguments"])})}_promptWillCheckAuthorities(ctx){if(this.tracingEnabled)onEntryWillCheckAuthorities(ctx)}_promptDidCheckAuthorities(ctx){if(this.tracingEnabled)onEntryDidCheckAuthorities(ctx)}_promptWillExecute(ctx){if(this.tracingEnabled)onPromptWillExecute(this.tracingOpts,ctx)}_promptDidExecute(ctx){if(this.tracingEnabled)onPromptDidExecute(ctx)}_promptFinallyFinalize(ctx){if(this.tracingEnabled)onPromptDidFinalize(ctx);if(!this.requestLogsEnabled)return;recordRequestLogFailure(ctx);recordRequestLogOutput(ctx)}_agentWillParse(ctx){this.watchHooks(ctx);if(this.tracingEnabled)onAgentWillParse(this.tracingOpts,ctx)}_agentWillFind(ctx){if(this.tracingEnabled)onAgentWillFind(ctx)}_agentWillCheckAuthorities(ctx){if(this.tracingEnabled)onEntryWillCheckAuthorities(ctx)}_agentDidCheckAuthorities(ctx){if(this.tracingEnabled)onEntryDidCheckAuthorities(ctx)}_agentWillExecute(ctx){if(this.tracingEnabled)onAgentWillExecute(this.tracingOpts,ctx)}_agentDidExecute(ctx){if(this.tracingEnabled)onAgentDidExecute(ctx)}_agentFinallyFinalize(ctx){if(this.tracingEnabled)onAgentDidFinalize(ctx)}_listToolsWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("tools/list",this.tracingOpts,ctx)}_listToolsDidFind(ctx){if(this.tracingEnabled)onGenericFlowStage("findTools",ctx)}_listToolsDidFilter(ctx){if(this.tracingEnabled)onGenericFlowStage("filterByAuthorities",ctx)}_listToolsDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_listResourcesWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("resources/list",this.tracingOpts,ctx)}_listResourcesDidFilter(ctx){if(this.tracingEnabled)onGenericFlowStage("filterByAuthorities",ctx)}_listResourcesDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_listTemplatesWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("resources/listTemplates",this.tracingOpts,ctx)}_listTemplatesDidFilter(ctx){if(this.tracingEnabled)onGenericFlowStage("filterByAuthorities",ctx)}_listTemplatesDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_listPromptsWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("prompts/list",this.tracingOpts,ctx)}_listPromptsDidFilter(ctx){if(this.tracingEnabled)onGenericFlowStage("filterByAuthorities",ctx)}_listPromptsDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillSearchWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills/search",this.tracingOpts,ctx)}_skillSearchDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillLoadWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills/load",this.tracingOpts,ctx)}_skillLoadStage(ctx){if(this.tracingEnabled)onGenericFlowStage("loadSkills",ctx)}_skillLoadDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_completionWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("completion/complete",this.tracingOpts,ctx)}_completionDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_sseWillParse(ctx){if(this.tracingEnabled)onTransportWillStart("legacy-sse",this.tracingOpts,ctx)}_sseDidRoute(ctx){if(this.tracingEnabled)onTransportDidRoute(ctx)}_sseDidInit(ctx){if(this.tracingEnabled)onTransportStage("onInitialize",ctx)}_sseDidMsg(ctx){if(this.tracingEnabled)onTransportStage("onMessage",ctx)}_sseDidElicit(ctx){if(this.tracingEnabled)onTransportStage("onElicitResult",ctx)}_sseFinallyCleanup(ctx){if(this.tracingEnabled)onTransportDidFinalize(ctx)}_shttpWillParse(ctx){if(this.tracingEnabled)onTransportWillStart("streamable-http",this.tracingOpts,ctx)}_shttpDidRoute(ctx){if(this.tracingEnabled)onTransportDidRoute(ctx)}_shttpDidInit(ctx){if(this.tracingEnabled)onTransportStage("onInitialize",ctx)}_shttpDidMsg(ctx){if(this.tracingEnabled)onTransportStage("onMessage",ctx)}_shttpDidElicit(ctx){if(this.tracingEnabled)onTransportStage("onElicitResult",ctx)}_shttpDidSse(ctx){if(this.tracingEnabled)onTransportStage("onSseListener",ctx)}_shttpDidExtApps(ctx){if(this.tracingEnabled)onTransportStage("onExtApps",ctx)}_shttpFinallyCleanup(ctx){if(this.tracingEnabled)onTransportDidFinalize(ctx)}_slhttpWillParse(ctx){if(this.tracingEnabled)onTransportWillStart("stateless-http",this.tracingOpts,ctx)}_slhttpDidHandle(ctx){if(this.tracingEnabled)onTransportStage("handleRequest",ctx)}_slhttpFinallyCleanup(ctx){if(this.tracingEnabled)onTransportDidFinalize(ctx)}_oauthTokenWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/token",this.tracingOpts,ctx)}_oauthTokenDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_oauthAuthzWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/authorize",this.tracingOpts,ctx)}_oauthAuthzDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_oauthCallbackWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/callback",this.tracingOpts,ctx)}_oauthCallbackDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_oauthProviderWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/provider-callback",this.tracingOpts,ctx)}_oauthProviderDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_oauthRegisterWill(ctx){if(this.traces("oauthSpans"))onGenericFlowWillStart("oauth/register",this.tracingOpts,ctx)}_oauthRegisterDone(ctx){if(this.traces("oauthSpans"))onGenericFlowDidFinalize(ctx)}_elicitReqWill(ctx){if(this.traces("elicitationSpans"))onGenericFlowWillStart("elicitation/request",this.tracingOpts,ctx)}_elicitReqDone(ctx){if(this.traces("elicitationSpans"))onGenericFlowDidFinalize(ctx)}_elicitResWill(ctx){if(this.traces("elicitationSpans"))onGenericFlowWillStart("elicitation/result",this.tracingOpts,ctx)}_elicitResDone(ctx){if(this.traces("elicitationSpans"))onGenericFlowDidFinalize(ctx)}_subscribeWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("resources/subscribe",this.tracingOpts,ctx)}_subscribeDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_unsubscribeWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("resources/unsubscribe",this.tracingOpts,ctx)}_unsubscribeDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillsLlmTxtWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills-http/llm-txt",this.tracingOpts,ctx)}_skillsLlmTxtDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillsLlmFullTxtWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills-http/llm-full-txt",this.tracingOpts,ctx)}_skillsLlmFullTxtDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_skillsApiWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("skills-http/api",this.tracingOpts,ctx)}_skillsApiDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_jwksWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("well-known/jwks",this.tracingOpts,ctx)}_jwksDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_oauthServerWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("well-known/oauth-server",this.tracingOpts,ctx)}_oauthServerDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_prmWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("well-known/prm",this.tracingOpts,ctx)}_prmDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_setLevelWill(ctx){if(this.tracingEnabled)onGenericFlowWillStart("logging/set-level",this.tracingOpts,ctx)}_setLevelDone(ctx){if(this.tracingEnabled)onGenericFlowDidFinalize(ctx)}_toolDidCreateCtxFetch(ctx){if(this.tracingEnabled)wrapContextFetch(this.tracingOpts,ctx)}_agentDidExecuteMeta(ctx){if(this.tracingEnabled)onAgentDidExecuteEnrich(ctx)}reportStartupTelemetry(data){if(this.traces("startupReport"))reportStartup(data)}};ObservabilityPlugin.defaultOptions={tracing:DEFAULT_TRACING,logging:false,requestLogs:false,stalls:false,devEvents:false};ObservabilityPlugin.dynamicProviders=input=>{const options=resolveOptions(input);const providers=[];if(options.tracing!==false){providers.push({name:"observability:tracer",provide:OTEL_TRACER,useValue:trace6.getTracer("@frontmcp/observability")});providers.push({name:"observability:config",provide:OTEL_CONFIG,useValue:options.tracing});providers.push({name:"observability:telemetry-accessor",provide:TELEMETRY_ACCESSOR,scope:ProviderScope.CONTEXT,inject:()=>[FRONTMCP_CONTEXT2],useFactory:ctx=>new TelemetryAccessor(ctx)});providers.push({name:"observability:telemetry-factory",provide:TELEMETRY_FACTORY,useValue:new TelemetryFactory})}if(options.logging!==false){const loggingOpts=options.logging;const sinks=createSinks(loggingOpts.sinks);const transport=new StructuredLogTransport(sinks,{redactFields:loggingOpts.redactFields,includeStacks:loggingOpts.includeStacks,staticFields:loggingOpts.staticFields},void 0);providers.push({name:"observability:structured-log-transport",provide:StructuredLogTransport,useValue:transport})}if(options.requestLogs!==false){const requestLogOpts=options.requestLogs;providers.push({name:"observability:request-log-collector",provide:REQUEST_LOG_COLLECTOR,scope:ProviderScope.CONTEXT,inject:()=>[FRONTMCP_CONTEXT2],useFactory:ctx=>{return new RequestLogCollector({requestId:ctx.requestId,traceId:ctx.traceContext.traceId,sessionIdHash:sessionTracingId(ctx.sessionId).slice(0,12),scopeId:ctx.scopeId},requestLogOpts)}})}if(options.stalls!==false||options.devEvents!==false){const{stalls,devEvents}=options;providers.push({name:"observability:call-monitor",provide:CallMonitor,inject:()=>[FRONTMCP_LOGGER],useFactory:logger=>new CallMonitor(stalls,devEvents,logger.child("CallMonitor"))})}return providers};__decorateClass([HttpHook.Will("traceRequest",{priority:-1e3})],ObservabilityPlugin.prototype,"_httpWillTrace",1);__decorateClass([HttpHook.Will("acquireQuota",{priority:-1e3})],ObservabilityPlugin.prototype,"_httpWillQuota",1);__decorateClass([HttpHook.Did("acquireSemaphore",{priority:1e3})],ObservabilityPlugin.prototype,"_httpDidSemaphore",1);__decorateClass([HttpHook.Will("checkAuthorization",{priority:-1e3})],ObservabilityPlugin.prototype,"_httpWillAuth",1);__decorateClass([HttpHook.Did("checkAuthorization",{priority:1e3})],ObservabilityPlugin.prototype,"_httpDidAuth",1);__decorateClass([HttpHook.Finally("checkAuthorization",{priority:1e3})],ObservabilityPlugin.prototype,"_httpFinallyAuth",1);__decorateClass([HttpHook.Will("router",{priority:-1e3})],ObservabilityPlugin.prototype,"_httpWillRoute",1);__decorateClass([HttpHook.Did("router",{priority:1e3})],ObservabilityPlugin.prototype,"_httpDidRoute",1);__decorateClass([HttpHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_httpFinallyFinalize",1);__decorateClass([ToolHook2.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillParse",1);__decorateClass([ToolHook2.Will("findTool",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillFind",1);__decorateClass([ToolHook2.Will("checkToolAuthorization",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillCheckAuth",1);__decorateClass([ToolHook2.Will("checkEntryAuthorities",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillCheckAuthorities",1);__decorateClass([ToolHook2.Did("checkEntryAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_toolDidCheckAuthorities",1);__decorateClass([ToolHook2.Will("createToolCallContext",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillCreateCtx",1);__decorateClass([ToolHook2.Will("validateInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillValidate",1);__decorateClass([ToolHook2.Will("execute",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillExecute",1);__decorateClass([ToolHook2.Did("execute",{priority:1e3})],ObservabilityPlugin.prototype,"_toolDidExecute",1);__decorateClass([ToolHook2.Will("validateOutput",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillValidateOut",1);__decorateClass([ToolHook2.Will("applyUI",{priority:-1e3})],ObservabilityPlugin.prototype,"_toolWillApplyUI",1);__decorateClass([ToolHook2.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_toolFinallyFinalize",1);__decorateClass([ResourceHook2.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_resourceWillParse",1);__decorateClass([ResourceHook2.Will("findResource",{priority:-1e3})],ObservabilityPlugin.prototype,"_resourceWillFind",1);__decorateClass([ResourceHook2.Will("checkEntryAuthorities",{priority:-1e3})],ObservabilityPlugin.prototype,"_resourceWillCheckAuthorities",1);__decorateClass([ResourceHook2.Did("checkEntryAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_resourceDidCheckAuthorities",1);__decorateClass([ResourceHook2.Will("execute",{priority:-1e3})],ObservabilityPlugin.prototype,"_resourceWillExecute",1);__decorateClass([ResourceHook2.Did("execute",{priority:1e3})],ObservabilityPlugin.prototype,"_resourceDidExecute",1);__decorateClass([ResourceHook2.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_resourceFinallyFinalize",1);__decorateClass([PromptHook2.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_promptWillParse",1);__decorateClass([PromptHook2.Will("findPrompt",{priority:-1e3})],ObservabilityPlugin.prototype,"_promptWillFind",1);__decorateClass([PromptHook2.Will("checkEntryAuthorities",{priority:-1e3})],ObservabilityPlugin.prototype,"_promptWillCheckAuthorities",1);__decorateClass([PromptHook2.Did("checkEntryAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_promptDidCheckAuthorities",1);__decorateClass([PromptHook2.Will("execute",{priority:-1e3})],ObservabilityPlugin.prototype,"_promptWillExecute",1);__decorateClass([PromptHook2.Did("execute",{priority:1e3})],ObservabilityPlugin.prototype,"_promptDidExecute",1);__decorateClass([PromptHook2.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_promptFinallyFinalize",1);__decorateClass([AgentCallHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_agentWillParse",1);__decorateClass([AgentCallHook.Will("findAgent",{priority:-1e3})],ObservabilityPlugin.prototype,"_agentWillFind",1);__decorateClass([AgentCallHook.Will("checkEntryAuthorities",{priority:-1e3})],ObservabilityPlugin.prototype,"_agentWillCheckAuthorities",1);__decorateClass([AgentCallHook.Did("checkEntryAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_agentDidCheckAuthorities",1);__decorateClass([AgentCallHook.Will("execute",{priority:-1e3})],ObservabilityPlugin.prototype,"_agentWillExecute",1);__decorateClass([AgentCallHook.Did("execute",{priority:1e3})],ObservabilityPlugin.prototype,"_agentDidExecute",1);__decorateClass([AgentCallHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_agentFinallyFinalize",1);__decorateClass([ListToolsHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_listToolsWill",1);__decorateClass([ListToolsHook.Did("findTools",{priority:1e3})],ObservabilityPlugin.prototype,"_listToolsDidFind",1);__decorateClass([ListToolsHook.Did("filterByAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_listToolsDidFilter",1);__decorateClass([ListToolsHook.Did("parseTools",{priority:1e3})],ObservabilityPlugin.prototype,"_listToolsDone",1);__decorateClass([ListResourcesHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_listResourcesWill",1);__decorateClass([ListResourcesHook.Did("filterByAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_listResourcesDidFilter",1);__decorateClass([ListResourcesHook.Did("parseResources",{priority:1e3})],ObservabilityPlugin.prototype,"_listResourcesDone",1);__decorateClass([ListResourceTemplatesHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_listTemplatesWill",1);__decorateClass([ListResourceTemplatesHook.Did("filterByAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_listTemplatesDidFilter",1);__decorateClass([ListResourceTemplatesHook.Did("parseTemplates",{priority:1e3})],ObservabilityPlugin.prototype,"_listTemplatesDone",1);__decorateClass([ListPromptsHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_listPromptsWill",1);__decorateClass([ListPromptsHook.Did("filterByAuthorities",{priority:1e3})],ObservabilityPlugin.prototype,"_listPromptsDidFilter",1);__decorateClass([ListPromptsHook.Did("parsePrompts",{priority:1e3})],ObservabilityPlugin.prototype,"_listPromptsDone",1);__decorateClass([SkillSearchHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillSearchWill",1);__decorateClass([SkillSearchHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_skillSearchDone",1);__decorateClass([SkillLoadHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillLoadWill",1);__decorateClass([SkillLoadHook.Will("loadSkills",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillLoadStage",1);__decorateClass([SkillLoadHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_skillLoadDone",1);__decorateClass([CompletionHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_completionWill",1);__decorateClass([CompletionHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_completionDone",1);__decorateClass([LegacySseHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_sseWillParse",1);__decorateClass([LegacySseHook.Did("router",{priority:1e3})],ObservabilityPlugin.prototype,"_sseDidRoute",1);__decorateClass([LegacySseHook.Did("onInitialize",{priority:1e3})],ObservabilityPlugin.prototype,"_sseDidInit",1);__decorateClass([LegacySseHook.Did("onMessage",{priority:1e3})],ObservabilityPlugin.prototype,"_sseDidMsg",1);__decorateClass([LegacySseHook.Did("onElicitResult",{priority:1e3})],ObservabilityPlugin.prototype,"_sseDidElicit",1);__decorateClass([LegacySseHook.Finally("cleanup",{priority:1e3})],ObservabilityPlugin.prototype,"_sseFinallyCleanup",1);__decorateClass([StreamableHttpHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_shttpWillParse",1);__decorateClass([StreamableHttpHook.Did("router",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidRoute",1);__decorateClass([StreamableHttpHook.Did("onInitialize",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidInit",1);__decorateClass([StreamableHttpHook.Did("onMessage",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidMsg",1);__decorateClass([StreamableHttpHook.Did("onElicitResult",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidElicit",1);__decorateClass([StreamableHttpHook.Did("onSseListener",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidSse",1);__decorateClass([StreamableHttpHook.Did("onExtApps",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpDidExtApps",1);__decorateClass([StreamableHttpHook.Finally("cleanup",{priority:1e3})],ObservabilityPlugin.prototype,"_shttpFinallyCleanup",1);__decorateClass([StatelessHttpHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_slhttpWillParse",1);__decorateClass([StatelessHttpHook.Did("handleRequest",{priority:1e3})],ObservabilityPlugin.prototype,"_slhttpDidHandle",1);__decorateClass([StatelessHttpHook.Finally("cleanup",{priority:1e3})],ObservabilityPlugin.prototype,"_slhttpFinallyCleanup",1);__decorateClass([OAuthTokenHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthTokenWill",1);__decorateClass([OAuthTokenHook.Did("buildTokenResponse",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthTokenDone",1);__decorateClass([OAuthAuthorizeHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthAuthzWill",1);__decorateClass([OAuthAuthorizeHook.Did("buildAuthorizeOutput",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthAuthzDone",1);__decorateClass([OAuthCallbackHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthCallbackWill",1);__decorateClass([OAuthCallbackHook.Did("redirectToClient",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthCallbackDone",1);__decorateClass([OAuthProviderCallbackHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthProviderWill",1);__decorateClass([OAuthProviderCallbackHook.Did("handleNextProviderOrComplete",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthProviderDone",1);__decorateClass([OAuthRegisterHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthRegisterWill",1);__decorateClass([OAuthRegisterHook.Did("respondRegistration",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthRegisterDone",1);__decorateClass([ElicitRequestHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_elicitReqWill",1);__decorateClass([ElicitRequestHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_elicitReqDone",1);__decorateClass([ElicitResultHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_elicitResWill",1);__decorateClass([ElicitResultHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_elicitResDone",1);__decorateClass([SubscribeResourceHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_subscribeWill",1);__decorateClass([SubscribeResourceHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_subscribeDone",1);__decorateClass([UnsubscribeResourceHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_unsubscribeWill",1);__decorateClass([UnsubscribeResourceHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_unsubscribeDone",1);__decorateClass([SkillsHttpLlmTxtHook.Will("checkEnabled",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillsLlmTxtWill",1);__decorateClass([SkillsHttpLlmTxtHook.Did("generateContent",{priority:1e3})],ObservabilityPlugin.prototype,"_skillsLlmTxtDone",1);__decorateClass([SkillsHttpLlmFullTxtHook.Will("checkEnabled",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillsLlmFullTxtWill",1);__decorateClass([SkillsHttpLlmFullTxtHook.Did("generateContent",{priority:1e3})],ObservabilityPlugin.prototype,"_skillsLlmFullTxtDone",1);__decorateClass([SkillsHttpApiHook.Will("checkEnabled",{priority:-1e3})],ObservabilityPlugin.prototype,"_skillsApiWill",1);__decorateClass([SkillsHttpApiHook.Did("handleRequest",{priority:1e3})],ObservabilityPlugin.prototype,"_skillsApiDone",1);__decorateClass([WellKnownJwksHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_jwksWill",1);__decorateClass([WellKnownJwksHook.Did("collectData",{priority:1e3})],ObservabilityPlugin.prototype,"_jwksDone",1);__decorateClass([WellKnownOAuthServerHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_oauthServerWill",1);__decorateClass([WellKnownOAuthServerHook.Did("collectData",{priority:1e3})],ObservabilityPlugin.prototype,"_oauthServerDone",1);__decorateClass([WellKnownPrmHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_prmWill",1);__decorateClass([WellKnownPrmHook.Did("collectData",{priority:1e3})],ObservabilityPlugin.prototype,"_prmDone",1);__decorateClass([LoggingSetLevelHook.Will("parseInput",{priority:-1e3})],ObservabilityPlugin.prototype,"_setLevelWill",1);__decorateClass([LoggingSetLevelHook.Finally("finalize",{priority:1e3})],ObservabilityPlugin.prototype,"_setLevelDone",1);__decorateClass([ToolHook2.Did("createToolCallContext",{priority:999})],ObservabilityPlugin.prototype,"_toolDidCreateCtxFetch",1);__decorateClass([AgentCallHook.Did("execute",{priority:999})],ObservabilityPlugin.prototype,"_agentDidExecuteMeta",1);ObservabilityPlugin=__decorateClass([Plugin({name:"observability",description:"Full-system OpenTelemetry instrumentation, structured logging, and request logs",providers:[],contextExtensions:[{property:"telemetry",token:TELEMETRY_ACCESSOR,errorMessage:"ObservabilityPlugin is not installed or tracing is disabled. Add ObservabilityPlugin.init() to your plugins array."}]})],ObservabilityPlugin);function resolveOptions(input){return{tracing:resolveTracingOptions(input.tracing),logging:resolveLoggingOptions(input.logging),requestLogs:resolveRequestLogOptions(input.requestLogs),stalls:resolveStallOptions(input.stalls),devEvents:resolveDevEventsOptions(input.devEvents)}}function resolveTracingOptions(input){if(input===false)return false;if(input===true||input===void 0)return DEFAULT_TRACING;return{...DEFAULT_TRACING,...input}}function resolveLoggingOptions(input){if(input===false||input===void 0)return false;if(input===true)return{};return input}function resolveRequestLogOptions(input){if(input===false||input===void 0)return false;if(input===true)return{};return input}import{trace as trace7}from"@opentelemetry/api";var TRACEPARENT_HEADER="traceparent";var FrontMcpPropagator=class{inject(context,carrier,setter){const span=trace7.getSpan(context);if(!span)return;const sc=span.spanContext();if(!sc||!isValidSpanContext(sc))return;const flags=sc.traceFlags.toString(16).padStart(2,"0");const traceparent=`00-${sc.traceId}-${sc.spanId}-${flags}`;setter.set(carrier,TRACEPARENT_HEADER,traceparent)}extract(context,carrier,getter){const traceparent=getter.get(carrier,TRACEPARENT_HEADER);const value=Array.isArray(traceparent)?traceparent[0]:traceparent;if(!value)return context;const parsed=parseTraceparent(value);if(!parsed)return context;const spanContext={traceId:parsed.traceId,spanId:parsed.parentId,traceFlags:parsed.traceFlags,isRemote:true};const span=trace7.wrapSpanContext(spanContext);return trace7.setSpan(context,span)}fields(){return[TRACEPARENT_HEADER]}};function parseTraceparent(value){const parts=value.split("-");if(parts.length!==4)return null;const[version,traceId,parentId,flags]=parts;if(version!=="00")return null;if(!/^[a-f0-9]{32}$/i.test(traceId)||traceId==="00000000000000000000000000000000")return null;if(!/^[a-f0-9]{16}$/i.test(parentId)||parentId==="0000000000000000")return null;if(!/^[0-9a-fA-F]{2}$/.test(flags))return null;const traceFlags=parseInt(flags,16);return{traceId:traceId.toLowerCase(),parentId:parentId.toLowerCase(),traceFlags}}function isValidSpanContext(sc){return sc.traceId!=="00000000000000000000000000000000"&&sc.spanId!=="0000000000000000"&&sc.traceId.length===32&&sc.spanId.length===16}function setupOTel(options){const serviceName=options?.serviceName??process.env["OTEL_SERVICE_NAME"]??"frontmcp-server";const exporterType=options?.exporter??"console";const endpoint=options?.endpoint??process.env["OTEL_EXPORTER_OTLP_ENDPOINT"]??"http://localhost:4318";let traceExporter;if(exporterType==="otlp"){try{const{OTLPTraceExporter}=__require("@opentelemetry/exporter-trace-otlp-http");traceExporter=new OTLPTraceExporter({url:`${endpoint}/v1/traces`})}catch{throw new Error("setupOTel: @opentelemetry/exporter-trace-otlp-http is required for OTLP export. Install it with: npm install @opentelemetry/exporter-trace-otlp-http")}}else if(exporterType==="console"){const{ConsoleSpanExporter}=__require("@opentelemetry/sdk-trace-base");traceExporter=new ConsoleSpanExporter}try{const{NodeSDK}=__require("@opentelemetry/sdk-node");const{resourceFromAttributes}=__require("@opentelemetry/resources");const{ATTR_SERVICE_NAME,ATTR_SERVICE_VERSION}=__require("@opentelemetry/semantic-conventions");const resource=resourceFromAttributes({[ATTR_SERVICE_NAME]:serviceName,...options?.serviceVersion?{[ATTR_SERVICE_VERSION]:options.serviceVersion}:{}});const sdk=new NodeSDK({resource,traceExporter});sdk.start();return async()=>{await sdk.shutdown()}}catch{throw new Error("setupOTel: @opentelemetry/sdk-node is required. Install it with: npm install @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/semantic-conventions")}}import{SpanKind as SpanKind14,SpanStatusCode as SpanStatusCode5}from"@opentelemetry/api";var RESET="\x1B[0m";var DIM="\x1B[2m";var BOLD="\x1B[1m";var CYAN="\x1B[36m";var GREEN="\x1B[32m";var RED="\x1B[31m";var YELLOW="\x1B[33m";var KIND_LABELS={[SpanKind14.INTERNAL]:"INTERNAL",[SpanKind14.SERVER]:"SERVER",[SpanKind14.CLIENT]:"CLIENT",[SpanKind14.PRODUCER]:"PRODUCER",[SpanKind14.CONSUMER]:"CONSUMER"};var SHOW_ATTRS=new Set(["rpc.system","rpc.method","rpc.service","mcp.method.name","mcp.session.id","mcp.component.type","mcp.component.key","http.request.method","http.response.status_code","url.path","frontmcp.tool.name","frontmcp.tool.owner","frontmcp.transport.type","frontmcp.transport.request_type","frontmcp.auth.mode","frontmcp.auth.result","frontmcp.flow.name","enduser.id"]);var PrettySpanExporter=class{constructor(){this.useAnsi=typeof process!=="undefined"&&!!process.stdout?.isTTY}export(spans,resultCallback){for(const span of spans){console.log(this.format(span))}resultCallback({code:0})}shutdown(){return Promise.resolve()}format(span){const traceShort=span.spanContext().traceId.slice(0,8);const durationMs=(span.duration[0]*1e3+span.duration[1]/1e6).toFixed(1);const kind=KIND_LABELS[span.kind]??"UNKNOWN";const statusOk=span.status.code!==SpanStatusCode5.ERROR;const attrs=Object.entries(span.attributes).filter(([k])=>SHOW_ATTRS.has(k)).map(([k,v])=>{const short=k.replace("frontmcp.","").replace("mcp.","");return`${short}=${v}`}).join(" ");const eventCount=span.events.length;const eventSummary=eventCount>0?` (${eventCount} events)`:"";if(this.useAnsi){const statusColor=statusOk?GREEN:RED;const kindColor=span.kind===SpanKind14.SERVER?CYAN:DIM;return[`${DIM}\u21B3${RESET}`,`${BOLD}${statusColor}SPAN${RESET}`,`${BOLD}${span.name}${RESET}`,`${DIM}[${traceShort}]${RESET}`,`${YELLOW}${durationMs}ms${RESET}`,`${kindColor}${kind}${RESET}`,attrs?`${DIM}${attrs}${RESET}`:"",eventSummary?`${DIM}${eventSummary}${RESET}`:""].filter(Boolean).join(" ")}return["\u21B3 SPAN",span.name,`[${traceShort}]`,`${durationMs}ms`,kind,attrs,eventSummary].filter(Boolean).join(" ")}};init_winston_sink();init_pino_sink();init_otlp_sink();import{redactFields as redactFields2}from"@frontmcp/utils";var METRIC_NAME_REGEX=/^[a-zA-Z_:][a-zA-Z0-9_:]*$/;var LABEL_NAME_REGEX=/^[a-zA-Z_][a-zA-Z0-9_]*$/;var PROMETHEUS_CONTENT_TYPE="text/plain; version=0.0.4; charset=utf-8";function escapeLabelValue(value){return value.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}function sortedLabelString(attributes){const keys=Object.keys(attributes).filter(k=>LABEL_NAME_REGEX.test(k)).sort();if(keys.length===0)return"";const pairs=keys.map(k=>`${k}="${escapeLabelValue(attributes[k]??"")}"`);return`{${pairs.join(",")}}`}function formatFloat(value){if(!Number.isFinite(value))return"";if(Number.isInteger(value))return String(value);return String(value)}function renderPrometheusExposition(counters,gauges=[],options={}){const byName=new Map;for(const entry of counters){if(!METRIC_NAME_REGEX.test(entry.name))continue;const valueStr=formatFloat(entry.count);if(valueStr==="")continue;const labels=sortedLabelString(entry.attributes??{});const line=`${entry.name}${labels} ${valueStr}`;let group=byName.get(entry.name);if(!group){group={type:"counter",help:options.counterHelp?.[entry.name],lines:[]};byName.set(entry.name,group)}group.lines.push(line)}for(const entry of gauges){if(!METRIC_NAME_REGEX.test(entry.name))continue;const valueStr=formatFloat(entry.value);if(valueStr==="")continue;const labels=sortedLabelString(entry.attributes??{});const line=`${entry.name}${labels} ${valueStr}`;let group=byName.get(entry.name);if(!group){group={type:"gauge",help:entry.help,lines:[]};byName.set(entry.name,group)}else if(entry.help&&!group.help){group.help=entry.help}group.lines.push(line)}if(byName.size===0)return"";const sortedNames=Array.from(byName.keys()).sort();const blocks=[];for(const name of sortedNames){const group=byName.get(name);if(!group)continue;const block=[];if(group.help){block.push(`# HELP ${name} ${group.help.replace(/\n/g," ")}`)}block.push(`# TYPE ${name} ${group.type}`);block.push(...group.lines.slice().sort());blocks.push(block.join("\n"))}return blocks.join("\n")+"\n"}function renderJsonExposition(counters,gauges=[]){return{counters:counters.filter(c=>METRIC_NAME_REGEX.test(c.name)&&Number.isFinite(c.count)).map(c=>({name:c.name,count:c.count,attributes:{...c.attributes??{}}})),gauges:gauges.filter(g=>METRIC_NAME_REGEX.test(g.name)&&Number.isFinite(g.value)).map(g=>({name:g.name,value:g.value,attributes:{...g.attributes??{}},...g.help?{help:g.help}:{}}))}}import{readdirSync}from"@frontmcp/utils";var NS_PER_SECOND=1e9;var MICROS_PER_SECOND=1e6;function probeSafely(probe){try{return probe()}catch{return void 0}}function defaultMonitorEventLoopDelay(){try{const{monitorEventLoopDelay}=__require("node:perf_hooks");const histogram=monitorEventLoopDelay({resolution:10});histogram.enable();return histogram}catch{return void 0}}function defaultGetActiveHandles(){const proc=process;if(typeof proc._getActiveHandles!=="function")return void 0;try{return proc._getActiveHandles()}catch{return void 0}}function defaultGetActiveRequests(){const proc=process;if(typeof proc._getActiveRequests!=="function")return void 0;try{return proc._getActiveRequests()}catch{return void 0}}function defaultReadFdCount(){if(process.platform!=="linux")return void 0;try{return readdirSync("/proc/self/fd").length}catch{return void 0}}var ProcessStatsCollector=class{constructor(init={}){this.options=init.options??{};this.cpuUsage=init.cpuUsage??(prev=>process.cpuUsage(prev));this.memoryUsage=init.memoryUsage??(()=>process.memoryUsage());this.uptime=init.uptime??(()=>process.uptime());this.getActiveHandles=init.getActiveHandles??defaultGetActiveHandles;this.getActiveRequests=init.getActiveRequests??defaultGetActiveRequests;this.readFdCount=init.readFdCount??defaultReadFdCount;this.cpuStart=probeSafely(()=>this.cpuUsage());if(this.options.eventLoopLag!==false){this.histogram=init.monitorEventLoopDelay?init.monitorEventLoopDelay():defaultMonitorEventLoopDelay()}}collect(){const entries=[];this.cpuStart??=probeSafely(()=>this.cpuUsage());const cpu=this.cpuStart&&probeSafely(()=>this.cpuUsage(this.cpuStart));if(cpu){entries.push({name:"frontmcp_process_cpu_seconds_total",value:cpu.user/MICROS_PER_SECOND,attributes:{mode:"user"},help:"CPU time consumed since collector start, by mode (seconds)"});entries.push({name:"frontmcp_process_cpu_seconds_total",value:cpu.system/MICROS_PER_SECOND,attributes:{mode:"system"}})}const mem=probeSafely(()=>this.memoryUsage());if(mem&&mem.rss>0){entries.push({name:"frontmcp_process_resident_memory_bytes",value:mem.rss,help:"Resident memory size in bytes"});entries.push({name:"frontmcp_process_heap_bytes",value:mem.heapTotal,help:"Total V8 heap size in bytes"});entries.push({name:"frontmcp_process_heap_used_bytes",value:mem.heapUsed,help:"Used V8 heap size in bytes"});entries.push({name:"frontmcp_process_external_bytes",value:mem.external,help:"Memory used by C++ objects bound to JS in bytes"})}const uptime=probeSafely(()=>this.uptime());if(uptime!==void 0&&uptime>0){entries.push({name:"frontmcp_process_uptime_seconds",value:uptime,help:"Time since process start in seconds"})}const histogram=this.options.eventLoopLag!==false?this.histogram:void 0;const lag=histogram&&probeSafely(()=>{const sample={meanSeconds:histogram.mean/NS_PER_SECOND,p99Seconds:histogram.percentile(99)/NS_PER_SECOND};histogram.reset();return sample});if(lag){const{meanSeconds,p99Seconds}=lag;if(Number.isFinite(meanSeconds)){entries.push({name:"frontmcp_nodejs_eventloop_lag_seconds",value:meanSeconds,attributes:{quantile:"mean"},help:"Event-loop lag in seconds, sampled at 10ms resolution since the last scrape"})}if(Number.isFinite(p99Seconds)){entries.push({name:"frontmcp_nodejs_eventloop_lag_seconds",value:p99Seconds,attributes:{quantile:"p99"}})}}if(this.options.activeHandles!==false){const handles=this.getActiveHandles?.();if(handles!==void 0){entries.push({name:"frontmcp_nodejs_active_handles",value:handles.length,help:"Currently active libuv handles (sockets, timers, etc.)"})}const requests=this.getActiveRequests?.();if(requests!==void 0){entries.push({name:"frontmcp_nodejs_active_requests",value:requests.length,help:"Currently active libuv requests (file I/O, DNS, etc.)"})}}if(this.options.fdCount!==false){const fdCount=this.readFdCount();if(typeof fdCount==="number"){entries.push({name:"frontmcp_nodejs_open_fds",value:fdCount,help:"Number of open file descriptors (Linux only)"})}}return entries}close(){this.histogram?.disable?.()}};function createTestTracer(name="test"){const sdkTraceBase=__require("@opentelemetry/sdk-trace-base");const exporter=new sdkTraceBase.InMemorySpanExporter;const provider=new sdkTraceBase.BasicTracerProvider({spanProcessors:[new sdkTraceBase.SimpleSpanProcessor(exporter)]});const tracer=provider.getTracer(name);return{tracer,exporter,provider,cleanup:async()=>{exporter.reset();await provider.forceFlush();await provider.shutdown()}}}function getFinishedSpans(exporter){return exporter.getFinishedSpans()}function assertSpanExists(spans,name){const match=spans.find(s=>s.name===name);if(!match){const names=spans.map(s=>s.name).join(", ");throw new Error(`Expected span "${name}" but found: [${names}]`)}return match}function assertSpanAttribute(span,key,value){const actual=span.attributes[key];if(actual!==value){throw new Error(`Expected span "${span.name}" attribute "${key}" to be ${JSON.stringify(value)} but got ${JSON.stringify(actual)}`)}}function findSpan(spans,name){return spans.find(s=>s.name===name)}function findSpansByAttribute(spans,key,value){return spans.filter(s=>s.attributes[key]===value)}export{CallMonitor,CallbackSink,ConsoleSink,DevEventStream,EnduserAttributes,FrontMcpAttributes,FrontMcpPropagator,HttpAttributes,InFlightCalls,IpcDevEventSink,JsonlFileSink,KNOWN_BUNDLE_SOURCES,KNOWN_ERROR_REASONS,LOG_LEVEL_TO_OTEL_SEVERITY,McpAttributes,OTEL_CONFIG,OTEL_TRACER,ObservabilityConfigurationError,ObservabilityPlugin,OtlpSink,PROMETHEUS_CONTENT_TYPE,PinoSink,PrettySpanExporter,ProcessStatsCollector,REQUEST_LOG_COLLECTOR,RequestLogCollector,RpcAttributes,STALL_SECONDS_COUNTER,StallDetector,StdoutSink,StructuredLogTransport,TELEMETRY_ACCESSOR,TELEMETRY_FACTORY,TelemetryAccessor,TelemetryFactory,TelemetrySpan,WinstonSink,assertSpanAttribute,assertSpanExists,countStall,createCounter,createOTelContextFromTrace,createSink,createSinks,createTestTracer,describeStall,emitStartupReport,endSpanError,endSpanOk,findSpan,findSpansByAttribute,frontmcpToOTelSpanContext,getCounterTotal,getFinishedSpans,getMetricSnapshot,normalizeBundleSource,normalizeErrorReason,otelToFrontmcpContext,recordHookEvent,redactFields2 as redactFields,renderJsonExposition,renderPrometheusExposition,reportStartup,resetCounterCacheForTesting,resetMetricSnapshot,resetTelemetrySnapshotForTesting,sessionTracingId,setAuthMode,setAuthResult,setFetchResponseStatus,setHttpResponseStatus,setTransportRequestType,setupOTel,startAuthSpan,startFetchSpan,startHookSpan,startHttpServerSpan,startPromptSpan,startResourceSpan,startRpcSpan,startSpan,startToolSpan,startTransportSpan,withSpan};