@agimon-ai/log-sink-mcp 0.2.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +11 -11
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +22 -22
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{stdio-D5FY3NXS.cjs → stdio-D-S2Mhwk.cjs} +17 -17
- package/dist/stdio-D-S2Mhwk.cjs.map +1 -0
- package/dist/stdio-DSDgdLCE.mjs +245 -0
- package/dist/stdio-DSDgdLCE.mjs.map +1 -0
- package/package.json +3 -3
- package/dist/stdio-7vqC2Ouf.mjs +0 -245
- package/dist/stdio-7vqC2Ouf.mjs.map +0 -1
- package/dist/stdio-D5FY3NXS.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`./chunk-DjWAcSYV.cjs`),t=require(`./stdio-
|
|
1
|
+
const e=require(`./chunk-DjWAcSYV.cjs`),t=require(`./stdio-D-S2Mhwk.cjs`),n=require(`./node-DnZY4eWX.cjs`);let r=require(`@opentelemetry/api`),i=require(`@opentelemetry/api-logs`);exports.StdioTransportHandler=t.t,exports.createNodeTelemetry=n.t,exports.createServer=t.n,exports.log=i.logs,exports.resolveLogSinkPort=n.n,exports.trace=r.trace;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./stdio-
|
|
1
|
+
import{n as e,t}from"./stdio-DSDgdLCE.mjs";import{i as n,n as r,r as i,t as a}from"./node-BXUuvy4I.mjs";export{t as StdioTransportHandler,a as createNodeTelemetry,e as createServer,r as log,n as resolveLogSinkPort,i as trace};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node:path`);n=e.t(n);let r=require(`node:url`),i=require(`@agimon-ai/foundation-port-registry`),a=require(`@agimon-ai/foundation-process-registry`),o=require(`inversify`);require(`reflect-metadata`);let s=require(`node:child_process`),c=require(`node:fs/promises`);c=e.t(c);let l=require(`node:os`),u=require(`node:module`);u=e.t(u);let d=require(`node:sqlite`),f=require(`ulidx`),p=require(`sqlite-vec`);p=e.t(p);let m=require(`@modelcontextprotocol/sdk/server/index.js`),h=require(`@modelcontextprotocol/sdk/types.js`),g=require(`@modelcontextprotocol/sdk/server/stdio.js`);function _(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}let v=class{defaultTimeout=5e3;async check(e,t=this.defaultTimeout){try{let n=`http://localhost:${e}/health`,r=new AbortController,i=setTimeout(()=>r.abort(),t);try{let t=await fetch(n,{signal:r.signal,headers:{"Content-Type":`application/json`}});if(clearTimeout(i),!t.ok)return{healthy:!1,error:`HTTP error ${t.status}: ${t.statusText}`};let a=await t.json();return a.status===`healthy`?{healthy:!0,port:e,serviceName:a.serviceName??a.service}:{healthy:!1,error:`Unexpected health status: ${a.status||`unknown`}`}}catch(e){return clearTimeout(i),e instanceof Error?e.name===`AbortError`?{healthy:!1,error:`Health check timed out after ${t}ms`}:`code`in e&&e.code===`ECONNREFUSED`?{healthy:!1,error:`Connection refused - server not running`}:{healthy:!1,error:`Network error: ${e.message}`}:{healthy:!1,error:`Unknown error: ${String(e)}`}}}catch(e){return{healthy:!1,error:e instanceof Error?e.message:String(e)}}}};v=_([(0,o.injectable)()],v);const y={LogStorageService:Symbol.for(`LogStorageService`),EmbeddingService:Symbol.for(`EmbeddingService`),LogQueryService:Symbol.for(`LogQueryService`),LogSearchService:Symbol.for(`LogSearchService`),SemanticSearchService:Symbol.for(`SemanticSearchService`),LogRetentionService:Symbol.for(`LogRetentionService`),HttpServerHealthCheck:Symbol.for(`HttpServerHealthCheck`),HttpServerManager:Symbol.for(`HttpServerManager`),Database:Symbol.for(`Database`),Logger:Symbol.for(`Logger`),HttpServer:Symbol.for(`HttpServer`),McpServer:Symbol.for(`McpServer`)},b=[`pnpm-workspace.yaml`,`nx.json`,`.git`];function x(e=process.cwd()){let r=(0,n.resolve)(e);for(;;){for(let e of b)if((0,t.existsSync)((0,n.join)(r,e)))return r;let e=(0,n.dirname)(r);if(e===r)return process.cwd();r=e}}function S(e){let t=(0,n.basename)(x(e));return(0,n.join)((0,l.tmpdir)(),`log-sink-mcp`,t,`session.db`)}function C(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function w(e,t){return function(n,r){t(n,r,e)}}const T=(0,r.fileURLToPath)(require(`url`).pathToFileURL(__filename).href),E=n.default.dirname(T);function D(e,t){if(!e)return;let r=n.default.resolve(e);return n.default.extname(r)===`.json`?n.default.join(n.default.dirname(r),t):n.default.join(r,t)}let O=class{repositoryPath;environment;serviceName=`log-sink-mcp-http`;serviceType=`tool`;host=`127.0.0.1`;registryPath;portRegistry;processRegistry;constructor(e,t,r){this.healthCheck=e,this.repositoryPath=x(t?n.default.resolve(t):process.cwd()),this.environment=process.env.NODE_ENV||`development`,this.registryPath=r||process.env.PORT_REGISTRY_PATH,this.portRegistry=new i.PortRegistryService(this.registryPath),this.processRegistry=new a.ProcessRegistryService(D(this.registryPath,`processes.json`))}async getRegistration(){let e=await this.portRegistry.getPort({repositoryPath:this.repositoryPath,serviceName:this.serviceName,serviceType:this.serviceType,environment:this.environment});return!e.success||!e.record?null:{port:e.record.port,pid:e.record.pid,environment:e.record.environment??this.environment,host:e.record.host,metadata:e.record.metadata}}async releaseService(e){let t=await this.portRegistry.releasePort({repositoryPath:this.repositoryPath,serviceName:this.serviceName,serviceType:this.serviceType,environment:this.environment,...e?{pid:e}:{}});if(!t.success&&!t.error?.includes(`No matching registry entry`))throw Error(t.error||`Failed to release registry entry`)}async releaseProcess(e){let t=await this.processRegistry.releaseProcess({repositoryPath:this.repositoryPath,serviceName:this.serviceName,serviceType:this.serviceType,environment:this.environment,...e?{pid:e}:{},kill:!1,releasePort:!1});if(!t.success&&!t.error?.includes(`No matching process entry`))throw Error(t.error||`Failed to release process entry`)}async findAvailablePort(e){let t=await this.portRegistry.findAvailablePort({repositoryPath:this.repositoryPath,serviceName:this.serviceName,serviceType:this.serviceType,environment:this.environment,host:this.host,preferredPort:e});if(!t.success||!t.port)throw Error(`No available port found from ${e}: ${t.error}`);return t.port}async fileExists(e){try{return await c.default.access(e),!0}catch{return!1}}async startHttpServer(e,t){let r=[n.default.resolve(E,`cli.mjs`),n.default.resolve(E,`..`,`dist`,`cli.mjs`),n.default.resolve(E,`..`,`..`,`dist`,`cli.mjs`)],i=[n.default.resolve(E,`..`,`cli.ts`),n.default.resolve(E,`..`,`..`,`src`,`cli.ts`)],a;for(let e of r)if(await this.fileExists(e)){a=e;break}let o;if(!a){for(let e of i)if(await this.fileExists(e)){o=e;break}}let l,u;if(a)l=process.execPath,u=[a,`http-serve`,`--port`,e.toString()];else if(o)l=process.execPath,u=[`--import`,`tsx`,o,`http-serve`,`--port`,e.toString()];else throw Error(`Cannot find log-sink MCP CLI in any expected location`);let d=n.default.resolve(t);await c.default.mkdir(n.default.dirname(d),{recursive:!0});let f=(0,s.spawn)(l,[...u,`--db-path`,d],{detached:!0,stdio:`ignore`,env:{...process.env,...this.registryPath?{PORT_REGISTRY_PATH:this.registryPath}:{},NODE_ENV:this.environment}});f.unref();let p=f.pid;if(!p)throw Error(`Failed to spawn HTTP server - no PID returned`);return p}async waitForRegisteredService(e,t,n=10,r=250){for(let i=0;i<n;i+=1){let n=await this.getRegistration();if(n?.pid===t&&n.port===e)return n;await new Promise(e=>setTimeout(e,r))}return null}async waitForServerStartup(e=4e3){await new Promise(t=>setTimeout(t,e))}async killProcess(e){try{process.kill(e,0),process.kill(e,`SIGTERM`),await new Promise(e=>setTimeout(e,1e3));try{process.kill(e,0),process.kill(e,`SIGKILL`)}catch{}}catch{}}async ensureRunning(e=i.DEFAULT_PORT_RANGE.min,t=S()){try{let n=await this.getRegistration();if(n){let e=await this.healthCheck.check(n.port);if(e.healthy&&e.serviceName===this.serviceName)return{running:!0,port:n.port,pid:n.pid};n.pid&&await this.killProcess(n.pid),await this.releaseProcess(n.pid),await this.releaseService(n.pid)}let r=e;for(let e=0;e<3;e+=1){let e=await this.findAvailablePort(r),n=await this.startHttpServer(e,t);await this.waitForServerStartup();let i=await this.healthCheck.check(e);if(!i.healthy||i.serviceName!==this.serviceName){await this.killProcess(n),await this.releaseProcess(n),await this.releaseService(n),r=e+1;continue}if(!await this.waitForRegisteredService(e,n)){await this.killProcess(n),await this.releaseProcess(n),await this.releaseService(n),r=e+1;continue}return{running:!0,port:e,pid:n}}return{running:!1,error:`Failed to start log-sink-mcp HTTP server after retries`}}catch(e){return{running:!1,error:e instanceof Error?e.message:String(e)}}}async stop(){try{let e=await this.getRegistration();if(!e)return!1;try{if(e.pid&&process.kill(e.pid,`SIGTERM`),await new Promise(e=>setTimeout(e,1e3)),e.pid)try{process.kill(e.pid,0),process.kill(e.pid,`SIGKILL`)}catch{}}catch{}return await this.releaseProcess(e.pid),await this.releaseService(e.pid),!0}catch(e){throw Error(`Failed to stop HTTP server: ${e instanceof Error?e.message:String(e)}`)}}async getStatus(){try{let e=await this.getRegistration();if(!e)return{running:!1,error:`No HTTP server registered`};let t=await this.healthCheck.check(e.port);return t.healthy&&t.serviceName===this.serviceName?{running:!0,port:e.port,pid:e.pid}:{running:!1,port:e.port,pid:e.pid,error:t.error}}catch(e){return{running:!1,error:e instanceof Error?e.message:String(e)}}}};O=_([(0,o.injectable)(),w(0,(0,o.inject)(y.HttpServerHealthCheck)),w(1,(0,o.unmanaged)()),w(2,(0,o.unmanaged)()),C(`design:paramtypes`,[Object,String,String])],O);var k;function A(){let e=(0,n.dirname)((0,u.createRequire)(require(`url`).pathToFileURL(__filename).href).resolve(`ruvector-onnx-embeddings-wasm`)),r=(0,n.join)(e,`ruvector_onnx_embeddings_wasm.js`),i=(0,t.readFileSync)(r,`utf-8`),a=new u.default(r);return a.filename=r,a.paths=u.default._nodeModulePaths(e),a._compile(i,r),a.exports}let j=class{static{k=this}static DEFAULT_MODEL=`all-MiniLM-L6-v2`;static VECTOR_DIMENSION=384;static CACHE_DIR=(0,n.join)((0,l.homedir)(),`.log-sink-mcp`);embedderPromise=null;modelUnavailable=!1;loaderPromise=null;constructor(e){this.storage=e}get modelName(){return process.env.LOG_SINK_EMBEDDING_MODEL??k.DEFAULT_MODEL}async loadLoader(){return this.loaderPromise||=import(`ruvector-onnx-embeddings-wasm/loader.js`).catch(e=>{let t=e&&typeof e==`object`&&`code`in e?String(e.code):``,n=e instanceof Error?e.message:String(e);if(t===`ERR_MODULE_NOT_FOUND`||t===`MODULE_NOT_FOUND`||n.includes(`ruvector-onnx`))return null;throw e}),this.loaderPromise}async getEmbedder(){if(this.modelUnavailable)throw Error(`Embedding model is not available locally`);if(!this.embedderPromise){let e=await this.loadLoader();if(!e)throw this.modelUnavailable=!0,Error(`Embedding model support is disabled because ruvector-onnx-embeddings-wasm is not installed`);await(0,c.mkdir)(k.CACHE_DIR,{recursive:!0});let t=A();this.embedderPromise=this.createEmbedderWithCache(e,t).catch(e=>{throw this.embedderPromise=null,this.modelUnavailable=!0,e})}return this.embedderPromise}async createEmbedderWithCache(e,r){let i=this.modelName,a=e.MODELS[i];if(!a)throw Error(`Unknown embedding model: ${i}`);let o=(0,n.join)(k.CACHE_DIR,i),s=(0,n.join)(o,`model.onnx`),l=(0,n.join)(o,`tokenizer.json`),u,d;if((0,t.existsSync)(s)&&(0,t.existsSync)(l))[u,d]=await Promise.all([(0,c.readFile)(s).then(e=>new Uint8Array(e)),(0,c.readFile)(l,`utf-8`)]);else{await(0,c.mkdir)(o,{recursive:!0});let[e,t]=await Promise.all([fetch(a.model).then(e=>{if(!e.ok)throw Error(`Failed to download model: ${e.status}`);return e.arrayBuffer()}),fetch(a.tokenizer).then(e=>{if(!e.ok)throw Error(`Failed to download tokenizer: ${e.status}`);return e.text()})]);u=new Uint8Array(e),d=t,await Promise.all([(0,c.writeFile)(s,u),(0,c.writeFile)(l,d)])}let f=new r.WasmEmbedderConfig().setMaxLength(a.maxLength).setNormalize(!0).setPooling(0);return r.WasmEmbedder.withConfig(u,d,f)}async isAvailable(){if(this.modelUnavailable)return!1;try{return await this.getEmbedder(),!0}catch{return!1}}buildEmbeddingText(e){let t=e.metadata&&typeof e.metadata==`object`?JSON.stringify(e.metadata):e.metadata??``;return[`service: ${e.service}`,`level: ${e.level}`,`message: ${e.message}`,e.errorType?`errorType: ${e.errorType}`:null,e.errorMessage?`errorMessage: ${e.errorMessage}`:null,t?`metadata: ${t}`:null].filter(Boolean).join(`
|
|
2
|
-
`)}normalizeVector(e){let t=Math.sqrt(e.reduce((e,t)=>e+t*t,0));return t===0?e:e.map(e=>e/t)}toVector(e){if(e instanceof Float32Array||e instanceof Float64Array)return Array.from(e);if(Array.isArray(e)&&e.length>0&&typeof e[0]==`number`)return e;if(Array.isArray(e)&&e.length>0&&Array.isArray(e[0]))return e[0];throw Error(`Unexpected embedding output shape`)}async embedText(e){let t=await this.getEmbedder(),n=this.normalizeVector(this.toVector(t.embedOne(e)));if(n.length!==
|
|
1
|
+
const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node:path`);n=e.t(n);let r=require(`node:url`),i=require(`@agimon-ai/foundation-port-registry`),a=require(`@agimon-ai/foundation-process-registry`),o=require(`inversify`);require(`reflect-metadata`);let s=require(`node:child_process`),c=require(`node:fs/promises`);c=e.t(c);let l=require(`node:os`),u=require(`node:module`);u=e.t(u);let d=require(`node:sqlite`),f=require(`ulidx`),p=require(`sqlite-vec`);p=e.t(p);let m=require(`@modelcontextprotocol/sdk/server/index.js`),h=require(`@modelcontextprotocol/sdk/types.js`),g=require(`@modelcontextprotocol/sdk/server/stdio.js`);function _(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}let v=class{defaultTimeout=5e3;async check(e,t=this.defaultTimeout){try{let n=`http://localhost:${e}/health`,r=new AbortController,i=setTimeout(()=>r.abort(),t);try{let t=await fetch(n,{signal:r.signal,headers:{"Content-Type":`application/json`}});if(clearTimeout(i),!t.ok)return{healthy:!1,error:`HTTP error ${t.status}: ${t.statusText}`};let a=await t.json();return a.status===`healthy`?{healthy:!0,port:e,serviceName:a.serviceName??a.service}:{healthy:!1,error:`Unexpected health status: ${a.status||`unknown`}`}}catch(e){return clearTimeout(i),e instanceof Error?e.name===`AbortError`?{healthy:!1,error:`Health check timed out after ${t}ms`}:`code`in e&&e.code===`ECONNREFUSED`?{healthy:!1,error:`Connection refused - server not running`}:{healthy:!1,error:`Network error: ${e.message}`}:{healthy:!1,error:`Unknown error: ${String(e)}`}}}catch(e){return{healthy:!1,error:e instanceof Error?e.message:String(e)}}}};v=_([(0,o.injectable)()],v);const y={LogStorageService:Symbol.for(`LogStorageService`),EmbeddingService:Symbol.for(`EmbeddingService`),LogQueryService:Symbol.for(`LogQueryService`),LogSearchService:Symbol.for(`LogSearchService`),SemanticSearchService:Symbol.for(`SemanticSearchService`),LogRetentionService:Symbol.for(`LogRetentionService`),HttpServerHealthCheck:Symbol.for(`HttpServerHealthCheck`),HttpServerManager:Symbol.for(`HttpServerManager`),Database:Symbol.for(`Database`),Logger:Symbol.for(`Logger`),HttpServer:Symbol.for(`HttpServer`),McpServer:Symbol.for(`McpServer`)},b=[`pnpm-workspace.yaml`,`nx.json`,`.git`];function x(e=process.cwd()){let r=(0,n.resolve)(e);for(;;){for(let e of b)if((0,t.existsSync)((0,n.join)(r,e)))return r;let e=(0,n.dirname)(r);if(e===r)return process.cwd();r=e}}function S(e){let t=(0,n.basename)(x(e));return(0,n.join)((0,l.tmpdir)(),`log-sink-mcp`,t,`session.db`)}function C(e,t){if(typeof Reflect==`object`&&typeof Reflect.metadata==`function`)return Reflect.metadata(e,t)}function w(e,t){return function(n,r){t(n,r,e)}}const T=(0,r.fileURLToPath)(require(`url`).pathToFileURL(__filename).href),E=n.default.dirname(T);let D=class{repositoryPath;environment;serviceName=`log-sink-mcp-http`;serviceType=`tool`;host=`127.0.0.1`;registryPath;portRegistry;processRegistry;constructor(e,t,r){this.healthCheck=e,this.repositoryPath=x(t?n.default.resolve(t):process.cwd()),this.environment=process.env.NODE_ENV||`development`,this.registryPath=r||process.env.PORT_REGISTRY_PATH,this.portRegistry=new i.PortRegistryService(this.registryPath),this.processRegistry=new a.ProcessRegistryService((0,a.resolveSiblingRegistryPath)(this.registryPath,`processes.json`))}async getRegistration(){let e=await this.portRegistry.getPort({repositoryPath:this.repositoryPath,serviceName:this.serviceName,serviceType:this.serviceType,environment:this.environment});return!e.success||!e.record?null:{port:e.record.port,pid:e.record.pid,environment:e.record.environment??this.environment,host:e.record.host,metadata:e.record.metadata}}async releaseService(e){let t=await this.portRegistry.releasePort({repositoryPath:this.repositoryPath,serviceName:this.serviceName,serviceType:this.serviceType,environment:this.environment,...e?{pid:e}:{}});if(!t.success&&!t.error?.includes(`No matching registry entry`))throw Error(t.error||`Failed to release registry entry`)}async releaseProcess(e){let t=await this.processRegistry.releaseProcess({repositoryPath:this.repositoryPath,serviceName:this.serviceName,serviceType:this.serviceType,environment:this.environment,...e?{pid:e}:{},kill:!1,releasePort:!1});if(!t.success&&!t.error?.includes(`No matching process entry`))throw Error(t.error||`Failed to release process entry`)}async findAvailablePort(e){let t=await this.portRegistry.findAvailablePort({repositoryPath:this.repositoryPath,serviceName:this.serviceName,serviceType:this.serviceType,environment:this.environment,host:this.host,preferredPort:e});if(!t.success||!t.port)throw Error(`No available port found from ${e}: ${t.error}`);return t.port}async fileExists(e){try{return await c.default.access(e),!0}catch{return!1}}async startHttpServer(e,t){let r=[n.default.resolve(E,`cli.mjs`),n.default.resolve(E,`..`,`dist`,`cli.mjs`),n.default.resolve(E,`..`,`..`,`dist`,`cli.mjs`)],i=[n.default.resolve(E,`..`,`cli.ts`),n.default.resolve(E,`..`,`..`,`src`,`cli.ts`)],a;for(let e of r)if(await this.fileExists(e)){a=e;break}let o;if(!a){for(let e of i)if(await this.fileExists(e)){o=e;break}}let l,u;if(a)l=process.execPath,u=[a,`http-serve`,`--port`,e.toString()];else if(o)l=process.execPath,u=[`--import`,`tsx`,o,`http-serve`,`--port`,e.toString()];else throw Error(`Cannot find log-sink MCP CLI in any expected location`);let d=n.default.resolve(t);await c.default.mkdir(n.default.dirname(d),{recursive:!0});let f=(0,s.spawn)(l,[...u,`--db-path`,d],{detached:!0,stdio:`ignore`,env:{...process.env,...this.registryPath?{PORT_REGISTRY_PATH:this.registryPath}:{},NODE_ENV:this.environment}});f.unref();let p=f.pid;if(!p)throw Error(`Failed to spawn HTTP server - no PID returned`);return p}async waitForRegisteredService(e,t,n=10,r=250){for(let i=0;i<n;i+=1){let n=await this.getRegistration();if(n?.pid===t&&n.port===e)return n;await new Promise(e=>setTimeout(e,r))}return null}async waitForServerStartup(e=4e3){await new Promise(t=>setTimeout(t,e))}async killProcess(e){try{process.kill(e,0),process.kill(e,`SIGTERM`),await new Promise(e=>setTimeout(e,1e3));try{process.kill(e,0),process.kill(e,`SIGKILL`)}catch{}}catch{}}async ensureRunning(e=i.DEFAULT_PORT_RANGE.min,t=S()){try{let n=await this.getRegistration();if(n){let e=await this.healthCheck.check(n.port);if(e.healthy&&e.serviceName===this.serviceName)return{running:!0,port:n.port,pid:n.pid};n.pid&&await this.killProcess(n.pid),await this.releaseProcess(n.pid),await this.releaseService(n.pid)}let r=e;for(let e=0;e<3;e+=1){let e=await this.findAvailablePort(r),n=await this.startHttpServer(e,t);await this.waitForServerStartup();let i=await this.healthCheck.check(e);if(!i.healthy||i.serviceName!==this.serviceName){await this.killProcess(n),await this.releaseProcess(n),await this.releaseService(n),r=e+1;continue}if(!await this.waitForRegisteredService(e,n)){await this.killProcess(n),await this.releaseProcess(n),await this.releaseService(n),r=e+1;continue}return{running:!0,port:e,pid:n}}return{running:!1,error:`Failed to start log-sink-mcp HTTP server after retries`}}catch(e){return{running:!1,error:e instanceof Error?e.message:String(e)}}}async stop(){try{let e=await this.getRegistration();if(!e)return!1;try{if(e.pid&&process.kill(e.pid,`SIGTERM`),await new Promise(e=>setTimeout(e,1e3)),e.pid)try{process.kill(e.pid,0),process.kill(e.pid,`SIGKILL`)}catch{}}catch{}return await this.releaseProcess(e.pid),await this.releaseService(e.pid),!0}catch(e){throw Error(`Failed to stop HTTP server: ${e instanceof Error?e.message:String(e)}`)}}async getStatus(){try{let e=await this.getRegistration();if(!e)return{running:!1,error:`No HTTP server registered`};let t=await this.healthCheck.check(e.port);return t.healthy&&t.serviceName===this.serviceName?{running:!0,port:e.port,pid:e.pid}:{running:!1,port:e.port,pid:e.pid,error:t.error}}catch(e){return{running:!1,error:e instanceof Error?e.message:String(e)}}}};D=_([(0,o.injectable)(),w(0,(0,o.inject)(y.HttpServerHealthCheck)),w(1,(0,o.unmanaged)()),w(2,(0,o.unmanaged)()),C(`design:paramtypes`,[Object,String,String])],D);var O;function k(){let e=(0,n.dirname)((0,u.createRequire)(require(`url`).pathToFileURL(__filename).href).resolve(`ruvector-onnx-embeddings-wasm`)),r=(0,n.join)(e,`ruvector_onnx_embeddings_wasm.js`),i=(0,t.readFileSync)(r,`utf-8`),a=new u.default(r);return a.filename=r,a.paths=u.default._nodeModulePaths(e),a._compile(i,r),a.exports}let A=class{static{O=this}static DEFAULT_MODEL=`all-MiniLM-L6-v2`;static VECTOR_DIMENSION=384;static CACHE_DIR=(0,n.join)((0,l.homedir)(),`.log-sink-mcp`);embedderPromise=null;modelUnavailable=!1;loaderPromise=null;constructor(e){this.storage=e}get modelName(){return process.env.LOG_SINK_EMBEDDING_MODEL??O.DEFAULT_MODEL}async loadLoader(){return this.loaderPromise||=import(`ruvector-onnx-embeddings-wasm/loader.js`).catch(e=>{let t=e&&typeof e==`object`&&`code`in e?String(e.code):``,n=e instanceof Error?e.message:String(e);if(t===`ERR_MODULE_NOT_FOUND`||t===`MODULE_NOT_FOUND`||n.includes(`ruvector-onnx`))return null;throw e}),this.loaderPromise}async getEmbedder(){if(this.modelUnavailable)throw Error(`Embedding model is not available locally`);if(!this.embedderPromise){let e=await this.loadLoader();if(!e)throw this.modelUnavailable=!0,Error(`Embedding model support is disabled because ruvector-onnx-embeddings-wasm is not installed`);await(0,c.mkdir)(O.CACHE_DIR,{recursive:!0});let t=k();this.embedderPromise=this.createEmbedderWithCache(e,t).catch(e=>{throw this.embedderPromise=null,this.modelUnavailable=!0,e})}return this.embedderPromise}async createEmbedderWithCache(e,r){let i=this.modelName,a=e.MODELS[i];if(!a)throw Error(`Unknown embedding model: ${i}`);let o=(0,n.join)(O.CACHE_DIR,i),s=(0,n.join)(o,`model.onnx`),l=(0,n.join)(o,`tokenizer.json`),u,d;if((0,t.existsSync)(s)&&(0,t.existsSync)(l))[u,d]=await Promise.all([(0,c.readFile)(s).then(e=>new Uint8Array(e)),(0,c.readFile)(l,`utf-8`)]);else{await(0,c.mkdir)(o,{recursive:!0});let[e,t]=await Promise.all([fetch(a.model).then(e=>{if(!e.ok)throw Error(`Failed to download model: ${e.status}`);return e.arrayBuffer()}),fetch(a.tokenizer).then(e=>{if(!e.ok)throw Error(`Failed to download tokenizer: ${e.status}`);return e.text()})]);u=new Uint8Array(e),d=t,await Promise.all([(0,c.writeFile)(s,u),(0,c.writeFile)(l,d)])}let f=new r.WasmEmbedderConfig().setMaxLength(a.maxLength).setNormalize(!0).setPooling(0);return r.WasmEmbedder.withConfig(u,d,f)}async isAvailable(){if(this.modelUnavailable)return!1;try{return await this.getEmbedder(),!0}catch{return!1}}buildEmbeddingText(e){let t=e.metadata&&typeof e.metadata==`object`?JSON.stringify(e.metadata):e.metadata??``;return[`service: ${e.service}`,`level: ${e.level}`,`message: ${e.message}`,e.errorType?`errorType: ${e.errorType}`:null,e.errorMessage?`errorMessage: ${e.errorMessage}`:null,t?`metadata: ${t}`:null].filter(Boolean).join(`
|
|
2
|
+
`)}normalizeVector(e){let t=Math.sqrt(e.reduce((e,t)=>e+t*t,0));return t===0?e:e.map(e=>e/t)}toVector(e){if(e instanceof Float32Array||e instanceof Float64Array)return Array.from(e);if(Array.isArray(e)&&e.length>0&&typeof e[0]==`number`)return e;if(Array.isArray(e)&&e.length>0&&Array.isArray(e[0]))return e[0];throw Error(`Unexpected embedding output shape`)}async embedText(e){let t=await this.getEmbedder(),n=this.normalizeVector(this.toVector(t.embedOne(e)));if(n.length!==O.VECTOR_DIMENSION)throw Error(`Unexpected embedding dimension ${n.length}, expected ${O.VECTOR_DIMENSION}`);return n}async indexLogs(e){if(e.length!==0)try{let t=[];for(let n of e)t.push({log:n,embedding:await this.embedText(this.buildEmbeddingText(n))});let n=this.storage.getSqliteClient(),r=n.prepare(`
|
|
3
3
|
INSERT INTO log_embeddings (log_id, embedding, service, level, created_at)
|
|
4
4
|
VALUES (?, vec_f32(?), ?, ?, ?)
|
|
5
5
|
ON CONFLICT(log_id) DO UPDATE SET
|
|
@@ -7,7 +7,7 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
7
7
|
service = excluded.service,
|
|
8
8
|
level = excluded.level,
|
|
9
9
|
created_at = excluded.created_at
|
|
10
|
-
`);n.exec(`BEGIN`);try{for(let e of t)r.run(e.log.id,new Uint8Array(new Float32Array(e.embedding).buffer),e.log.service,e.log.level,Math.floor(e.log.createdAt.getTime()/1e3));n.exec(`COMMIT`)}catch(e){throw n.exec(`ROLLBACK`),e}}catch(e){console.warn(`Skipping semantic embedding indexing: ${e instanceof Error?e.message:String(e)}`)}}};
|
|
10
|
+
`);n.exec(`BEGIN`);try{for(let e of t)r.run(e.log.id,new Uint8Array(new Float32Array(e.embedding).buffer),e.log.service,e.log.level,Math.floor(e.log.createdAt.getTime()/1e3));n.exec(`COMMIT`)}catch(e){throw n.exec(`ROLLBACK`),e}}catch(e){console.warn(`Skipping semantic embedding indexing: ${e instanceof Error?e.message:String(e)}`)}}};A=O=_([(0,o.injectable)(),w(0,(0,o.inject)(y.LogStorageService)),C(`design:paramtypes`,[Object])],A);function j(e){return e}let M=class{constructor(e){this.storage=e}async getSqlite(){return await this.storage.ensureInitialized(),this.storage.getSqliteClient()}mapRow(e){return{id:e.id,timestamp:new Date(Number(e.timestamp)*1e3),level:e.level,message:e.message,traceId:e.trace_id,spanId:e.span_id,parentSpanId:e.parent_span_id,service:e.service,hostname:e.hostname,pid:e.pid,metadata:e.metadata?JSON.parse(e.metadata):null,errorType:e.error_type,errorMessage:e.error_message,errorStack:e.error_stack,createdAt:new Date(Number(e.created_at)*1e3)}}buildWhereClause(e){let t=`WHERE 1 = 1`,n=[];if(e.level){let r=Array.isArray(e.level)?e.level:[e.level];t+=` AND level IN (${r.map(()=>`?`).join(`,`)})`,n.push(...r)}if(e.service){let r=Array.isArray(e.service)?e.service:[e.service];t+=` AND service IN (${r.map(()=>`?`).join(`,`)})`,n.push(...r)}return e.traceId&&(t+=` AND trace_id = ?`,n.push(e.traceId)),e.startTime&&(t+=` AND timestamp >= ?`,n.push(Math.floor(e.startTime.getTime()/1e3))),e.endTime&&(t+=` AND timestamp <= ?`,n.push(Math.floor(e.endTime.getTime()/1e3))),{whereSql:t,params:n}}async filterByLevel(e,t=100){try{let n=await this.getSqlite(),{whereSql:r,params:i}=this.buildWhereClause({level:e});return j(n.prepare(`
|
|
11
11
|
SELECT
|
|
12
12
|
id, timestamp, level, message, trace_id, span_id, parent_span_id,
|
|
13
13
|
service, hostname, pid, metadata, error_type, error_message,
|
|
@@ -16,7 +16,7 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
16
16
|
${r}
|
|
17
17
|
ORDER BY timestamp DESC
|
|
18
18
|
LIMIT ?
|
|
19
|
-
`).all(...i,t)).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to filter by level: ${e instanceof Error?e.message:String(e)}`)}}async filterByTrace(e){try{return
|
|
19
|
+
`).all(...i,t)).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to filter by level: ${e instanceof Error?e.message:String(e)}`)}}async filterByTrace(e){try{return j((await this.getSqlite()).prepare(`
|
|
20
20
|
SELECT
|
|
21
21
|
id, timestamp, level, message, trace_id, span_id, parent_span_id,
|
|
22
22
|
service, hostname, pid, metadata, error_type, error_message,
|
|
@@ -24,7 +24,7 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
24
24
|
FROM logs
|
|
25
25
|
WHERE trace_id = ?
|
|
26
26
|
ORDER BY timestamp ASC
|
|
27
|
-
`).all(e)).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to filter by trace: ${e instanceof Error?e.message:String(e)}`)}}async filterByTimeRange(e,t){try{return
|
|
27
|
+
`).all(e)).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to filter by trace: ${e instanceof Error?e.message:String(e)}`)}}async filterByTimeRange(e,t){try{return j((await this.getSqlite()).prepare(`
|
|
28
28
|
SELECT
|
|
29
29
|
id, timestamp, level, message, trace_id, span_id, parent_span_id,
|
|
30
30
|
service, hostname, pid, metadata, error_type, error_message,
|
|
@@ -32,7 +32,7 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
32
32
|
FROM logs
|
|
33
33
|
WHERE timestamp >= ? AND timestamp <= ?
|
|
34
34
|
ORDER BY timestamp ASC
|
|
35
|
-
`).all(Math.floor(e.getTime()/1e3),Math.floor(t.getTime()/1e3))).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to filter by time range: ${e instanceof Error?e.message:String(e)}`)}}async filterByService(e){try{let t=await this.getSqlite(),n=Array.isArray(e)?e:[e];return
|
|
35
|
+
`).all(Math.floor(e.getTime()/1e3),Math.floor(t.getTime()/1e3))).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to filter by time range: ${e instanceof Error?e.message:String(e)}`)}}async filterByService(e){try{let t=await this.getSqlite(),n=Array.isArray(e)?e:[e];return j(t.prepare(`
|
|
36
36
|
SELECT
|
|
37
37
|
id, timestamp, level, message, trace_id, span_id, parent_span_id,
|
|
38
38
|
service, hostname, pid, metadata, error_type, error_message,
|
|
@@ -40,24 +40,24 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
40
40
|
FROM logs
|
|
41
41
|
WHERE service IN (${n.map(()=>`?`).join(`,`)})
|
|
42
42
|
ORDER BY timestamp ASC
|
|
43
|
-
`).all(...n)).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to filter by service: ${e instanceof Error?e.message:String(e)}`)}}async getTraceTimeline(e){try{let t=await this.filterByTrace(e),n=[];for(let e=0;e<t.length;e+=1){let r=t[e],i=t[e+1];n.push({timestamp:r.timestamp,service:r.service,spanId:r.spanId??null,parentSpanId:r.parentSpanId??null,level:r.level,message:r.message,duration:i?i.timestamp.getTime()-r.timestamp.getTime():void 0})}return n}catch(e){throw Error(`Failed to get trace timeline: ${e instanceof Error?e.message:String(e)}`)}}async getStatistics(e,t=`both`){try{let n=await this.getSqlite(),r=``,i=[];e&&(r=`WHERE timestamp >= ? AND timestamp <= ?`,i.push(Math.floor(e.start.getTime()/1e3),Math.floor(e.end.getTime()/1e3)));let a=`service, level, COUNT(*) as count`,o=`GROUP BY service, level`;return t===`level`?(a=`'' as service, level, COUNT(*) as count`,o=`GROUP BY level`):t===`service`&&(a=`service, '' as level, COUNT(*) as count`,o=`GROUP BY service`),
|
|
43
|
+
`).all(...n)).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to filter by service: ${e instanceof Error?e.message:String(e)}`)}}async getTraceTimeline(e){try{let t=await this.filterByTrace(e),n=[];for(let e=0;e<t.length;e+=1){let r=t[e],i=t[e+1];n.push({timestamp:r.timestamp,service:r.service,spanId:r.spanId??null,parentSpanId:r.parentSpanId??null,level:r.level,message:r.message,duration:i?i.timestamp.getTime()-r.timestamp.getTime():void 0})}return n}catch(e){throw Error(`Failed to get trace timeline: ${e instanceof Error?e.message:String(e)}`)}}async getStatistics(e,t=`both`){try{let n=await this.getSqlite(),r=``,i=[];e&&(r=`WHERE timestamp >= ? AND timestamp <= ?`,i.push(Math.floor(e.start.getTime()/1e3),Math.floor(e.end.getTime()/1e3)));let a=`service, level, COUNT(*) as count`,o=`GROUP BY service, level`;return t===`level`?(a=`'' as service, level, COUNT(*) as count`,o=`GROUP BY level`):t===`service`&&(a=`service, '' as level, COUNT(*) as count`,o=`GROUP BY service`),j(n.prepare(`
|
|
44
44
|
SELECT ${a}
|
|
45
45
|
FROM logs
|
|
46
46
|
${r}
|
|
47
47
|
${o}
|
|
48
|
-
`).all(...i)).map(e=>({service:e.service,level:e.level,count:Number(e.count)}))}catch(e){throw Error(`Failed to get statistics: ${e instanceof Error?e.message:String(e)}`)}}async getActiveServices(){try{return
|
|
48
|
+
`).all(...i)).map(e=>({service:e.service,level:e.level,count:Number(e.count)}))}catch(e){throw Error(`Failed to get statistics: ${e instanceof Error?e.message:String(e)}`)}}async getActiveServices(){try{return j((await this.getSqlite()).prepare(`SELECT DISTINCT service FROM logs ORDER BY service ASC`).all()).map(e=>e.service)}catch(e){throw Error(`Failed to get active services: ${e instanceof Error?e.message:String(e)}`)}}async countByLevel(e){try{let t=await this.getSqlite(),n=Array.isArray(e)?e:[e],r=t.prepare(`
|
|
49
49
|
SELECT COUNT(*) as count
|
|
50
50
|
FROM logs
|
|
51
51
|
WHERE level IN (${n.map(()=>`?`).join(`,`)})
|
|
52
|
-
`).all(...n);return Number(
|
|
52
|
+
`).all(...n);return Number(j(r)[0]?.count??0)}catch(e){throw Error(`Failed to count by level: ${e instanceof Error?e.message:String(e)}`)}}async countByService(e){try{let t=await this.getSqlite(),n=Array.isArray(e)?e:[e],r=t.prepare(`
|
|
53
53
|
SELECT COUNT(*) as count
|
|
54
54
|
FROM logs
|
|
55
55
|
WHERE service IN (${n.map(()=>`?`).join(`,`)})
|
|
56
|
-
`).all(...n);return Number(
|
|
56
|
+
`).all(...n);return Number(j(r)[0]?.count??0)}catch(e){throw Error(`Failed to count by service: ${e instanceof Error?e.message:String(e)}`)}}async countByTrace(e){try{let t=j((await this.getSqlite()).prepare(`SELECT COUNT(*) as count FROM logs WHERE trace_id = ?`).all(e));return Number(t[0]?.count??0)}catch(e){throw Error(`Failed to count by trace: ${e instanceof Error?e.message:String(e)}`)}}async queryLogs(e){try{let t=await this.getSqlite(),{level:n,service:r,traceId:i,limit:a=25,offset:o=0}=e,s={};n&&(s.level=n),r&&(s.service=r),i&&(s.traceId=i);let{whereSql:c,params:l}=this.buildWhereClause(s),u=j(t.prepare(`
|
|
57
57
|
SELECT COUNT(*) as count
|
|
58
58
|
FROM logs
|
|
59
59
|
${c}
|
|
60
|
-
`).all(...l));return{logs:
|
|
60
|
+
`).all(...l));return{logs:j(t.prepare(`
|
|
61
61
|
SELECT
|
|
62
62
|
id, timestamp, level, message, trace_id, span_id, parent_span_id,
|
|
63
63
|
service, hostname, pid, metadata, error_type, error_message,
|
|
@@ -67,7 +67,7 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
67
67
|
ORDER BY timestamp DESC
|
|
68
68
|
LIMIT ?
|
|
69
69
|
OFFSET ?
|
|
70
|
-
`).all(...l,a,o)).map(e=>this.mapRow(e)),total:Number(u[0]?.count??0)}}catch(e){throw Error(`Failed to query logs: ${e instanceof Error?e.message:String(e)}`)}}};
|
|
70
|
+
`).all(...l,a,o)).map(e=>this.mapRow(e)),total:Number(u[0]?.count??0)}}catch(e){throw Error(`Failed to query logs: ${e instanceof Error?e.message:String(e)}`)}}};M=_([(0,o.injectable)(),w(0,(0,o.inject)(y.LogStorageService)),C(`design:paramtypes`,[Object])],M);let N=class{sizeRetentionTimer=null;sizeRetentionRunPromise=null;constructor(e){this.storage=e}async getSqlite(){return await this.storage.ensureInitialized(),this.storage.getSqliteClient()}async cleanupOldLogs(e){try{let t=await this.getSqlite(),n=new Date;n.setDate(n.getDate()-e);let r=t.prepare(`DELETE FROM logs WHERE timestamp <= ?`).run(Math.floor(n.getTime()/1e3));return Number(r.changes??0)}catch(e){throw Error(`Failed to cleanup old logs: ${e instanceof Error?e.message:String(e)}`)}}async clearAllLogs(){try{return await this.storage.deleteAllLogs()}catch(e){throw Error(`Failed to clear all logs: ${e instanceof Error?e.message:String(e)}`)}}async cleanupOversizedDatabase(e){try{if(!Number.isFinite(e.maxBytes)||e.maxBytes<=0)throw Error(`maxBytes must be a positive number`);if(!Number.isFinite(e.intervalMs)||e.intervalMs<=0)throw Error(`intervalMs must be a positive number`);let t=e.batchSize??1e3,n=Math.min(e.targetBytes??Math.floor(e.maxBytes*.9),e.maxBytes),r=await this.storage.getDatabaseSizeBytes();if(r===null||r<=e.maxBytes)return{sizeBeforeBytes:r,sizeAfterBytes:r,deletedEntries:0,iterations:0,trimmed:!1};let i=r,a=0,o=0;for(;i>n;){let e=await this.storage.deleteOldestLogs(t);if(e===0)break;a+=e,o+=1,await this.storage.compactDatabase();let n=await this.storage.getDatabaseSizeBytes();n!==null&&(i=n)}return{sizeBeforeBytes:r,sizeAfterBytes:i,deletedEntries:a,iterations:o,trimmed:a>0}}catch(e){throw Error(`Failed to cleanup oversized database: ${e instanceof Error?e.message:String(e)}`)}}startSizeRetentionMonitor(e){this.stopSizeRetentionMonitor();let t=async()=>{this.sizeRetentionRunPromise||(this.sizeRetentionRunPromise=(async()=>{try{await this.cleanupOversizedDatabase(e)}catch(e){console.warn(`Failed to run periodic database retention: ${e instanceof Error?e.message:String(e)}`)}finally{this.sizeRetentionRunPromise=null}})(),await this.sizeRetentionRunPromise)};return t(),this.sizeRetentionTimer=setInterval(()=>{t()},e.intervalMs),this.sizeRetentionTimer.unref?.(),()=>{this.stopSizeRetentionMonitor()}}stopSizeRetentionMonitor(){this.sizeRetentionTimer&&=(clearInterval(this.sizeRetentionTimer),null)}};N=_([(0,o.injectable)(),w(0,(0,o.inject)(y.LogStorageService)),C(`design:paramtypes`,[Object])],N);function P(e){return e}let F=class{constructor(e){this.storage=e}async getSqlite(){return await this.storage.ensureInitialized(),this.storage.getSqliteClient()}buildSearchSql(e,t={}){let n=e.replace(/[^\w\s\-"*]/g,``).trim();if(!n)throw Error(`Search query is empty after sanitization`);let r=`WHERE logs_search MATCH ?`,i=[n];if(t.service){let e=Array.isArray(t.service)?t.service:[t.service];r+=` AND logs.service IN (${e.map(()=>`?`).join(`,`)})`,i.push(...e)}if(t.level){let e=Array.isArray(t.level)?t.level:[t.level];r+=` AND logs.level IN (${e.map(()=>`?`).join(`,`)})`,i.push(...e)}return t.startTime&&(r+=` AND logs.timestamp >= ?`,i.push(Math.floor(t.startTime.getTime()/1e3))),t.endTime&&(r+=` AND logs.timestamp <= ?`,i.push(Math.floor(t.endTime.getTime()/1e3))),{whereSql:r,params:i}}mapSearchRow(e){return{id:e.id,timestamp:new Date(e.timestamp*1e3),level:e.level,message:e.message,traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId,service:e.service,hostname:e.hostname,pid:e.pid,metadata:e.metadata?JSON.parse(e.metadata):null,errorType:e.errorType,errorMessage:e.errorMessage,errorStack:e.errorStack,createdAt:new Date(e.createdAt*1e3),rank:e.rank}}async searchLogs(e,t={},n=100){let{results:r}=await this.searchLogsPaginated(e,{...t,offset:0},n);return r}async searchLogsPaginated(e,t={},n=100){try{let r=await this.getSqlite(),{whereSql:i,params:a}=this.buildSearchSql(e,t),o=t.offset??0,s=`
|
|
71
71
|
SELECT COUNT(*) as total
|
|
72
72
|
FROM logs_search
|
|
73
73
|
JOIN logs ON logs.rowid = logs_search.rowid
|
|
@@ -96,7 +96,7 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
96
96
|
ORDER BY rank
|
|
97
97
|
LIMIT ?
|
|
98
98
|
OFFSET ?
|
|
99
|
-
`,l=r.prepare(s).get(...a);return{results:
|
|
99
|
+
`,l=r.prepare(s).get(...a);return{results:P(r.prepare(c).all(...a,n,o)).map(e=>this.mapSearchRow(e)),total:Number(l.total??0)}}catch(e){throw Error(`Failed to search logs: ${e instanceof Error?e.message:String(e)}`)}}rankResults(e){return e.sort((e,t)=>e.rank-t.rank)}};F=_([(0,o.injectable)(),w(0,(0,o.inject)(y.LogStorageService)),C(`design:paramtypes`,[Object])],F);function I(e){return e}let L=class{sqlite=null;embeddingWriter=null;databasePath=null;useInMemory=!1;setEmbeddingWriter(e){this.embeddingWriter=e}async initializeDatabase(e,t=!1){try{let r=t?`:memory:`:e;this.databasePath=r,this.useInMemory=t,t||await(0,c.mkdir)((0,n.dirname)(r),{recursive:!0}),this.sqlite=new d.DatabaseSync(r,{allowExtension:!0}),p.load(this.sqlite),t||this.sqlite.exec(`PRAGMA journal_mode = WAL`),this.sqlite.exec(`PRAGMA foreign_keys = ON`),this.sqlite.exec(`
|
|
100
100
|
CREATE TABLE IF NOT EXISTS logs (
|
|
101
101
|
id text PRIMARY KEY NOT NULL,
|
|
102
102
|
timestamp integer NOT NULL,
|
|
@@ -167,7 +167,7 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
167
167
|
error_stack, created_at
|
|
168
168
|
)
|
|
169
169
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
170
|
-
`);for(let t of n)e.run(t.id,Math.floor(t.timestamp.getTime()/1e3),t.level,t.message,t.traceId,t.spanId,t.parentSpanId,t.service,t.hostname,t.pid,t.metadata?JSON.stringify(t.metadata):null,t.errorType,t.errorMessage,t.errorStack,Math.floor(t.createdAt.getTime()/1e3));t.exec(`COMMIT`)}catch(e){throw t.exec(`ROLLBACK`),e}return await this.tryIndexEmbeddings(n),n}catch(e){throw Error(`Failed to insert batch: ${e instanceof Error?e.message:String(e)}`)}}async tryIndexEmbeddings(e){!this.embeddingWriter||e.length===0||this.embeddingWriter(e).catch(e=>{console.warn(`Failed to index semantic embeddings: ${e instanceof Error?e.message:String(e)}`)})}async queryLogs(e={}){try{let t=this.getSqliteClient(),n=`WHERE 1 = 1`,r=[];if(e.level){let t=Array.isArray(e.level)?e.level:[e.level];t.length===1?(n+=` AND level = ?`,r.push(t[0])):(n+=` AND level IN (${t.map(()=>`?`).join(`,`)})`,r.push(...t))}if(e.service){let t=Array.isArray(e.service)?e.service:[e.service];t.length===1?(n+=` AND service = ?`,r.push(t[0])):(n+=` AND service IN (${t.map(()=>`?`).join(`,`)})`,r.push(...t))}e.traceId&&(n+=` AND trace_id = ?`,r.push(e.traceId)),e.spanId&&(n+=` AND span_id = ?`,r.push(e.spanId)),e.errorType&&(n+=` AND error_type = ?`,r.push(e.errorType)),e.startTime&&(n+=` AND timestamp >= ?`,r.push(Math.floor(e.startTime.getTime()/1e3))),e.endTime&&(n+=` AND timestamp <= ?`,r.push(Math.floor(e.endTime.getTime()/1e3)));let i=e.limit??100,a=e.offset??0;return
|
|
170
|
+
`);for(let t of n)e.run(t.id,Math.floor(t.timestamp.getTime()/1e3),t.level,t.message,t.traceId,t.spanId,t.parentSpanId,t.service,t.hostname,t.pid,t.metadata?JSON.stringify(t.metadata):null,t.errorType,t.errorMessage,t.errorStack,Math.floor(t.createdAt.getTime()/1e3));t.exec(`COMMIT`)}catch(e){throw t.exec(`ROLLBACK`),e}return await this.tryIndexEmbeddings(n),n}catch(e){throw Error(`Failed to insert batch: ${e instanceof Error?e.message:String(e)}`)}}async tryIndexEmbeddings(e){!this.embeddingWriter||e.length===0||this.embeddingWriter(e).catch(e=>{console.warn(`Failed to index semantic embeddings: ${e instanceof Error?e.message:String(e)}`)})}async queryLogs(e={}){try{let t=this.getSqliteClient(),n=`WHERE 1 = 1`,r=[];if(e.level){let t=Array.isArray(e.level)?e.level:[e.level];t.length===1?(n+=` AND level = ?`,r.push(t[0])):(n+=` AND level IN (${t.map(()=>`?`).join(`,`)})`,r.push(...t))}if(e.service){let t=Array.isArray(e.service)?e.service:[e.service];t.length===1?(n+=` AND service = ?`,r.push(t[0])):(n+=` AND service IN (${t.map(()=>`?`).join(`,`)})`,r.push(...t))}e.traceId&&(n+=` AND trace_id = ?`,r.push(e.traceId)),e.spanId&&(n+=` AND span_id = ?`,r.push(e.spanId)),e.errorType&&(n+=` AND error_type = ?`,r.push(e.errorType)),e.startTime&&(n+=` AND timestamp >= ?`,r.push(Math.floor(e.startTime.getTime()/1e3))),e.endTime&&(n+=` AND timestamp <= ?`,r.push(Math.floor(e.endTime.getTime()/1e3)));let i=e.limit??100,a=e.offset??0;return I(t.prepare(`
|
|
171
171
|
SELECT
|
|
172
172
|
id,
|
|
173
173
|
timestamp,
|
|
@@ -189,7 +189,7 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
189
189
|
ORDER BY timestamp DESC
|
|
190
190
|
LIMIT ?
|
|
191
191
|
OFFSET ?
|
|
192
|
-
`).all(...r,i,a)).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to query logs: ${e instanceof Error?e.message:String(e)}`)}}async deleteAllLogs(){try{let e=this.getSqliteClient().prepare(`DELETE FROM logs`).run();return Number(e.changes??0)}catch(e){throw Error(`Failed to delete all logs: ${e instanceof Error?e.message:String(e)}`)}}async disconnect(){this.sqlite&&(this.sqlite.close(),this.sqlite=null,this.databasePath=null,this.useInMemory=!1)}};
|
|
192
|
+
`).all(...r,i,a)).map(e=>this.mapRow(e))}catch(e){throw Error(`Failed to query logs: ${e instanceof Error?e.message:String(e)}`)}}async deleteAllLogs(){try{let e=this.getSqliteClient().prepare(`DELETE FROM logs`).run();return Number(e.changes??0)}catch(e){throw Error(`Failed to delete all logs: ${e instanceof Error?e.message:String(e)}`)}}async disconnect(){this.sqlite&&(this.sqlite.close(),this.sqlite=null,this.databasePath=null,this.useInMemory=!1)}};L=_([(0,o.injectable)()],L);function R(e){return e}let z=class{constructor(e,t,n){this.storage=e,this.searchService=t,this.embeddings=n}async isAvailable(){return this.embeddings.isAvailable()}mapRow(e){let t=1/(1+e.distance);return{id:e.id,timestamp:new Date(e.timestamp*1e3),level:e.level,message:e.message,traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId,service:e.service,hostname:e.hostname,pid:e.pid,metadata:e.metadata?JSON.parse(e.metadata):null,errorType:e.errorType,errorMessage:e.errorMessage,errorStack:e.errorStack,createdAt:new Date(e.createdAt*1e3),distance:e.distance,score:t}}mapFallbackRow(e){return{...e,distance:1/0,score:1/(1+Math.max(0,Math.abs(e.rank)))}}buildFilterSql(e={}){let t=`WHERE 1 = 1`,n=[];if(e.service){let r=Array.isArray(e.service)?e.service:[e.service];t+=` AND logs.service IN (${r.map(()=>`?`).join(`,`)})`,n.push(...r)}if(e.level){let r=Array.isArray(e.level)?e.level:[e.level];t+=` AND logs.level IN (${r.map(()=>`?`).join(`,`)})`,n.push(...r)}return e.startTime&&(t+=` AND logs.timestamp >= ?`,n.push(Math.floor(e.startTime.getTime()/1e3))),e.endTime&&(t+=` AND logs.timestamp <= ?`,n.push(Math.floor(e.endTime.getTime()/1e3))),{whereSql:t,params:n}}async indexMissingLogs(e={},t=100){let n=this.storage.getSqliteClient(),r=0;for(;;){let{whereSql:i,params:a}=this.buildFilterSql(e),o=R(n.prepare(`
|
|
193
193
|
SELECT
|
|
194
194
|
logs.id as id,
|
|
195
195
|
logs.timestamp as timestamp,
|
|
@@ -241,5 +241,5 @@ const e=require(`./chunk-DjWAcSYV.cjs`);let t=require(`node:fs`),n=require(`node
|
|
|
241
241
|
ORDER BY distance ASC
|
|
242
242
|
LIMIT ?
|
|
243
243
|
OFFSET ?
|
|
244
|
-
`,d=r.prepare(l).get(...s);return{results:z(r.prepare(u).all(a,...s,n,c)).map(e=>this.mapRow(e)),total:Number(d.total??0)}}catch(r){let i=await this.searchService.searchLogsPaginated(e,t,n);return console.warn(`Semantic search unavailable, falling back to FTS: ${r instanceof Error?r.message:String(r)}`),{results:i.results.map(e=>this.mapFallbackRow(e)),total:i.total}}}};B=_([(0,o.injectable)(),w(0,(0,o.inject)(y.LogStorageService)),w(1,(0,o.inject)(y.LogSearchService)),w(2,(0,o.inject)(y.EmbeddingService)),C(`design:paramtypes`,[Object,Object,Object])],B);const V=new o.ContainerModule(e=>{e.bind(y.LogStorageService).to(R).inSingletonScope(),e.bind(y.EmbeddingService).to(j).inSingletonScope(),e.bind(y.LogQueryService).to(N).inSingletonScope(),e.bind(y.LogSearchService).to(I).inSingletonScope(),e.bind(y.SemanticSearchService).to(B).inSingletonScope(),e.bind(y.LogRetentionService).to(P).inSingletonScope(),e.bind(y.HttpServerHealthCheck).to(v).inSingletonScope(),e.bind(y.HttpServerManager).to(O).inSingletonScope()});function H(){let e=new o.Container;e.load(V);let t=e.get(y.LogStorageService),n=e.get(y.EmbeddingService);return t.setEmbeddingWriter(e=>n.indexLogs(e)),e}var U=class e{static TOOL_NAME=`analyze_errors`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Analyze error patterns and group similar errors by type and message. Calculates error frequencies, suggests root causes, and provides debugging insights.`,inputSchema:{type:`object`,properties:{timeRange:{type:`object`,properties:{start:{type:`string`,format:`date-time`,description:`Start time for error analysis (ISO 8601 format)`},end:{type:`string`,format:`date-time`,description:`End time for error analysis (ISO 8601 format)`}},description:`Optional time range to filter errors`},traceId:{type:`string`,description:`Optional trace ID to analyze errors within a specific trace`},limit:{type:`number`,minimum:1,maximum:1e3,default:100,description:`Maximum number of error entries to analyze`}},additionalProperties:!1}}}async execute(e){try{let t=e.limit??100,n;if(e.traceId)n=(await this.queryService.filterByTrace(e.traceId)).filter(e=>e.level===`error`||e.level===`fatal`).slice(0,t);else if(e.timeRange){let r=new Date(e.timeRange.start),i=new Date(e.timeRange.end);n=(await this.queryService.filterByTimeRange(r,i)).filter(e=>e.level===`error`||e.level===`fatal`).slice(0,t)}else n=await this.queryService.filterByLevel([`error`,`fatal`],t);let r=new Map;for(let e of n){let t=`${e.errorType}::${e.errorMessage}`;r.has(t)||r.set(t,{errorType:e.errorType,errorMessage:e.errorMessage,frequency:0,services:new Set,examples:[]});let n=r.get(t);n.frequency+=1,n.services.add(e.service),n.examples.length<3&&n.examples.push({id:e.id,timestamp:e.timestamp.toISOString(),service:e.service})}let i=Array.from(r.values()).sort((e,t)=>t.frequency-e.frequency).map(e=>({errorType:e.errorType,errorMessage:e.errorMessage,frequency:e.frequency,affectedServices:Array.from(e.services),examples:e.examples}));return{content:[{type:`text`,text:JSON.stringify({totalErrorsAnalyzed:n.length,uniqueErrorPatterns:i.length,analysis:i},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error analyzing logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},W=class e{static TOOL_NAME=`clear_logs`;retentionService;constructor(e){this.retentionService=e.get(y.LogRetentionService)}getDefinition(){return{name:e.TOOL_NAME,description:`Clear all logs from the database. Returns confirmation with count of deleted entries. Use with caution - this operation cannot be undone.`,inputSchema:{type:`object`,properties:{},additionalProperties:!1}}}async execute(e){try{let e=await this.retentionService.clearAllLogs();return{content:[{type:`text`,text:JSON.stringify({success:!0,message:`All logs have been cleared`,deletedEntries:e},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error clearing logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},G=class e{static TOOL_NAME=`get_log_stats`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Get aggregated log statistics grouped by level, service, or time period. Returns counts, distributions, and trends for log analysis.`,inputSchema:{type:`object`,properties:{startTime:{type:`string`,format:`date-time`,description:`Start time for statistics (ISO 8601 format)`},endTime:{type:`string`,format:`date-time`,description:`End time for statistics (ISO 8601 format)`},groupBy:{type:`string`,enum:[`level`,`service`,`both`],default:`both`,description:`Group statistics by 'level', 'service', or 'both'`}},additionalProperties:!1}}}async execute(e){try{let t;(e.startTime||e.endTime)&&(t={start:e.startTime?new Date(e.startTime):new Date(0),end:e.endTime?new Date(e.endTime):new Date});let n=e.groupBy??`both`,r=await this.queryService.getStatistics(t,n);return{content:[{type:`text`,text:JSON.stringify({timeRange:t,groupBy:n,totalEntries:r.reduce((e,t)=>e+t.count,0),statistics:r.map(e=>({service:e.service,level:e.level,count:e.count}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting statistics: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},K=class e{static TOOL_NAME=`get_services`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Get list of all unique services that have logged entries. Useful for discovering available services in the system.`,inputSchema:{type:`object`,properties:{},additionalProperties:!1}}}async execute(e){try{let e=await this.queryService.getActiveServices();return{content:[{type:`text`,text:JSON.stringify({count:e.length,services:e.sort()},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting services: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},q=class e{static TOOL_NAME=`get_trace_timeline`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Get complete trace timeline for a given trace ID, showing all log entries ordered by timestamp with span hierarchy visualization. Returns chronological sequence of events across services.`,inputSchema:{type:`object`,properties:{traceId:{type:`string`,description:`OTEL trace ID (32 hex characters)`}},required:[`traceId`],additionalProperties:!1}}}async execute(e){try{let t=await this.queryService.getTraceTimeline(e.traceId);return{content:[{type:`text`,text:JSON.stringify({traceId:e.traceId,count:t.length,timeline:t.map(e=>({timestamp:e.timestamp.toISOString(),service:e.service,spanId:e.spanId,parentSpanId:e.parentSpanId,level:e.level,message:e.message,duration:e.duration}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting trace timeline: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},J=class e{static TOOL_NAME=`query_logs`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Query and filter log entries by level, trace ID, time range, service, or other criteria. Returns filtered log entries with full metadata.`,inputSchema:{type:`object`,properties:{level:{oneOf:[{type:`string`,enum:[`trace`,`debug`,`info`,`warn`,`error`,`fatal`]},{type:`array`,items:{type:`string`,enum:[`trace`,`debug`,`info`,`warn`,`error`,`fatal`]}}],description:`Log level(s) to filter by`},traceId:{type:`string`,description:`Trace ID to filter by (OTEL format: 32 hex characters)`},service:{oneOf:[{type:`string`},{type:`array`,items:{type:`string`}}],description:`Service name(s) to filter by`},startTime:{type:`string`,format:`date-time`,description:`Start time for log range (ISO 8601 format)`},endTime:{type:`string`,format:`date-time`,description:`End time for log range (ISO 8601 format)`},limit:{type:`number`,minimum:1,maximum:1e3,default:100,description:`Maximum number of log entries to return`}},additionalProperties:!1}}}async execute(e){try{let t=e.limit??100,n;if(e.traceId)n=await this.queryService.filterByTrace(e.traceId),n=n.slice(0,t);else if(e.level)n=await this.queryService.filterByLevel(e.level,t);else if(e.service)n=await this.queryService.filterByService(e.service),n=n.slice(0,t);else if(e.startTime||e.endTime){let r=e.startTime?new Date(e.startTime):new Date(0),i=e.endTime?new Date(e.endTime):new Date;n=await this.queryService.filterByTimeRange(r,i),n=n.slice(0,t)}else n=await this.queryService.filterByLevel([`info`,`warn`,`error`,`fatal`],t);return{content:[{type:`text`,text:JSON.stringify({count:n.length,logs:n.map(e=>({id:e.id,timestamp:e.timestamp.toISOString(),level:e.level,message:e.message,service:e.service,traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId,hostname:e.hostname,pid:e.pid,metadata:e.metadata,errorType:e.errorType,errorMessage:e.errorMessage,errorStack:e.errorStack}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error querying logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},Y=class e{static TOOL_NAME=`search_logs`;searchService;semanticSearchService;constructor(e){this.searchService=e.get(y.LogSearchService),this.semanticSearchService=e.get(y.SemanticSearchService)}getDefinition(){return{name:e.TOOL_NAME,description:`Search log entries using FTS5, local semantic embeddings, or both. Hybrid mode combines exact text and semantic similarity for better incident retrieval.`,inputSchema:{type:`object`,properties:{searchQuery:{type:`string`,description:`FTS5 search query (supports phrase queries with quotes, prefix matching with *, boolean operators AND/OR/NOT)`},mode:{type:`string`,enum:[`fts`,`semantic`,`hybrid`],default:`hybrid`,description:`Search strategy to use`},service:{oneOf:[{type:`string`},{type:`array`,items:{type:`string`}}],description:`Service name(s) to filter by`},level:{oneOf:[{type:`string`,enum:[`trace`,`debug`,`info`,`warn`,`error`,`fatal`]},{type:`array`,items:{type:`string`,enum:[`trace`,`debug`,`info`,`warn`,`error`,`fatal`]}}],description:`Log level(s) to filter by`},startTime:{type:`string`,format:`date-time`,description:`Start time for log range (ISO 8601 format)`},endTime:{type:`string`,format:`date-time`,description:`End time for log range (ISO 8601 format)`},limit:{type:`number`,minimum:1,maximum:1e3,default:100,description:`Maximum number of search results to return`}},required:[`searchQuery`],additionalProperties:!1}}}async execute(e){try{let t={},n=e.mode??`hybrid`;e.service&&(t.service=e.service),e.level&&(t.level=e.level),e.startTime&&(t.startTime=new Date(e.startTime)),e.endTime&&(t.endTime=new Date(e.endTime));let r=e.limit??100,i=n===`semantic`?await this.semanticSearchService.searchLogs(e.searchQuery,t,r):n===`fts`?await this.searchService.searchLogs(e.searchQuery,t,r):await this.searchHybrid(e.searchQuery,t,r);return{content:[{type:`text`,text:JSON.stringify({mode:n,count:i.length,query:e.searchQuery,results:i.map(e=>({score:`score`in e?e.score:this.getFallbackScore(e.rank),rank:`rank`in e?e.rank:void 0,distance:`distance`in e?e.distance:void 0,sources:`sources`in e?e.sources:void 0,id:e.id,timestamp:e.timestamp.toISOString(),level:e.level,message:e.message,service:e.service,traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId,hostname:e.hostname,pid:e.pid,metadata:e.metadata,errorType:e.errorType,errorMessage:e.errorMessage}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error searching logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}getFallbackScore(e){return 1/(1+Math.max(0,Math.abs(e)))}async searchHybrid(e,t,n){let r=Math.max(n*2,50),i=this.searchService.searchLogs(e,t,r),a=await this.semanticSearchService.isAvailable(),o=await i;if(!a)return o;let s=await this.semanticSearchService.searchLogs(e,t,r),c=new Map;return o.forEach((e,t)=>{c.set(e.id,{result:e,score:.65*(1/(1+t)),rank:e.rank,sources:new Set([`fts`])})}),s.forEach((e,t)=>{let n=c.get(e.id),r=.35*(1/(1+t));n?(n.score+=r,n.sources.add(`semantic`),n.distance=e.distance,n.rank===void 0&&`rank`in e&&(n.rank=e.rank),n.result={...n.result,...e}):c.set(e.id,{result:e,score:r,distance:e.distance,sources:new Set([`semantic`])})}),Array.from(c.values()).sort((e,t)=>t.score-e.score).slice(0,n).map(e=>({...e.result,score:e.score,sources:Array.from(e.sources),rank:e.rank,distance:e.distance}))}};function X(e){let t=new m.Server({name:`log-sink-mcp`,version:`0.1.0`},{capabilities:{tools:{}}}),n=e??H(),r=new J(n),i=new Y(n),a=new q(n),o=new U(n),s=new G(n),c=new K(n),l=new W(n);return t.setRequestHandler(h.ListToolsRequestSchema,async()=>({tools:[r.getDefinition(),i.getDefinition(),a.getDefinition(),o.getDefinition(),s.getDefinition(),c.getDefinition(),l.getDefinition()]})),t.setRequestHandler(h.CallToolRequestSchema,async e=>{let{name:t,arguments:n}=e.params;try{switch(t){case`query_logs`:return await r.execute(n);case`search_logs`:return await i.execute(n);case`get_trace_timeline`:return await a.execute(n);case`analyze_errors`:return await o.execute(n);case`get_log_stats`:return await s.execute(n);case`get_services`:return await c.execute(n);case`clear_logs`:return await l.execute(n);default:throw Error(`Unknown tool: ${t}`)}}catch(e){return{content:[{type:`text`,text:`Error executing tool ${t}: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}}),t}var Z=class{server;transport=null;constructor(e){this.server=e}async start(){this.transport=new g.StdioServerTransport,await this.server.connect(this.transport)}async stop(){this.transport&&=(await this.transport.close(),null)}};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return J}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return U}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return X}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return G}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return Z}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return H}});
|
|
245
|
-
//# sourceMappingURL=stdio-
|
|
244
|
+
`,d=r.prepare(l).get(...s);return{results:R(r.prepare(u).all(a,...s,n,c)).map(e=>this.mapRow(e)),total:Number(d.total??0)}}catch(r){let i=await this.searchService.searchLogsPaginated(e,t,n);return console.warn(`Semantic search unavailable, falling back to FTS: ${r instanceof Error?r.message:String(r)}`),{results:i.results.map(e=>this.mapFallbackRow(e)),total:i.total}}}};z=_([(0,o.injectable)(),w(0,(0,o.inject)(y.LogStorageService)),w(1,(0,o.inject)(y.LogSearchService)),w(2,(0,o.inject)(y.EmbeddingService)),C(`design:paramtypes`,[Object,Object,Object])],z);const B=new o.ContainerModule(e=>{e.bind(y.LogStorageService).to(L).inSingletonScope(),e.bind(y.EmbeddingService).to(A).inSingletonScope(),e.bind(y.LogQueryService).to(M).inSingletonScope(),e.bind(y.LogSearchService).to(F).inSingletonScope(),e.bind(y.SemanticSearchService).to(z).inSingletonScope(),e.bind(y.LogRetentionService).to(N).inSingletonScope(),e.bind(y.HttpServerHealthCheck).to(v).inSingletonScope(),e.bind(y.HttpServerManager).to(D).inSingletonScope()});function V(){let e=new o.Container;e.load(B);let t=e.get(y.LogStorageService),n=e.get(y.EmbeddingService);return t.setEmbeddingWriter(e=>n.indexLogs(e)),e}var H=class e{static TOOL_NAME=`analyze_errors`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Analyze error patterns and group similar errors by type and message. Calculates error frequencies, suggests root causes, and provides debugging insights.`,inputSchema:{type:`object`,properties:{timeRange:{type:`object`,properties:{start:{type:`string`,format:`date-time`,description:`Start time for error analysis (ISO 8601 format)`},end:{type:`string`,format:`date-time`,description:`End time for error analysis (ISO 8601 format)`}},description:`Optional time range to filter errors`},traceId:{type:`string`,description:`Optional trace ID to analyze errors within a specific trace`},limit:{type:`number`,minimum:1,maximum:1e3,default:100,description:`Maximum number of error entries to analyze`}},additionalProperties:!1}}}async execute(e){try{let t=e.limit??100,n;if(e.traceId)n=(await this.queryService.filterByTrace(e.traceId)).filter(e=>e.level===`error`||e.level===`fatal`).slice(0,t);else if(e.timeRange){let r=new Date(e.timeRange.start),i=new Date(e.timeRange.end);n=(await this.queryService.filterByTimeRange(r,i)).filter(e=>e.level===`error`||e.level===`fatal`).slice(0,t)}else n=await this.queryService.filterByLevel([`error`,`fatal`],t);let r=new Map;for(let e of n){let t=`${e.errorType}::${e.errorMessage}`;r.has(t)||r.set(t,{errorType:e.errorType,errorMessage:e.errorMessage,frequency:0,services:new Set,examples:[]});let n=r.get(t);n.frequency+=1,n.services.add(e.service),n.examples.length<3&&n.examples.push({id:e.id,timestamp:e.timestamp.toISOString(),service:e.service})}let i=Array.from(r.values()).sort((e,t)=>t.frequency-e.frequency).map(e=>({errorType:e.errorType,errorMessage:e.errorMessage,frequency:e.frequency,affectedServices:Array.from(e.services),examples:e.examples}));return{content:[{type:`text`,text:JSON.stringify({totalErrorsAnalyzed:n.length,uniqueErrorPatterns:i.length,analysis:i},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error analyzing logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},U=class e{static TOOL_NAME=`clear_logs`;retentionService;constructor(e){this.retentionService=e.get(y.LogRetentionService)}getDefinition(){return{name:e.TOOL_NAME,description:`Clear all logs from the database. Returns confirmation with count of deleted entries. Use with caution - this operation cannot be undone.`,inputSchema:{type:`object`,properties:{},additionalProperties:!1}}}async execute(e){try{let e=await this.retentionService.clearAllLogs();return{content:[{type:`text`,text:JSON.stringify({success:!0,message:`All logs have been cleared`,deletedEntries:e},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error clearing logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},W=class e{static TOOL_NAME=`get_log_stats`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Get aggregated log statistics grouped by level, service, or time period. Returns counts, distributions, and trends for log analysis.`,inputSchema:{type:`object`,properties:{startTime:{type:`string`,format:`date-time`,description:`Start time for statistics (ISO 8601 format)`},endTime:{type:`string`,format:`date-time`,description:`End time for statistics (ISO 8601 format)`},groupBy:{type:`string`,enum:[`level`,`service`,`both`],default:`both`,description:`Group statistics by 'level', 'service', or 'both'`}},additionalProperties:!1}}}async execute(e){try{let t;(e.startTime||e.endTime)&&(t={start:e.startTime?new Date(e.startTime):new Date(0),end:e.endTime?new Date(e.endTime):new Date});let n=e.groupBy??`both`,r=await this.queryService.getStatistics(t,n);return{content:[{type:`text`,text:JSON.stringify({timeRange:t,groupBy:n,totalEntries:r.reduce((e,t)=>e+t.count,0),statistics:r.map(e=>({service:e.service,level:e.level,count:e.count}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting statistics: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},G=class e{static TOOL_NAME=`get_services`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Get list of all unique services that have logged entries. Useful for discovering available services in the system.`,inputSchema:{type:`object`,properties:{},additionalProperties:!1}}}async execute(e){try{let e=await this.queryService.getActiveServices();return{content:[{type:`text`,text:JSON.stringify({count:e.length,services:e.sort()},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting services: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},K=class e{static TOOL_NAME=`get_trace_timeline`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Get complete trace timeline for a given trace ID, showing all log entries ordered by timestamp with span hierarchy visualization. Returns chronological sequence of events across services.`,inputSchema:{type:`object`,properties:{traceId:{type:`string`,description:`OTEL trace ID (32 hex characters)`}},required:[`traceId`],additionalProperties:!1}}}async execute(e){try{let t=await this.queryService.getTraceTimeline(e.traceId);return{content:[{type:`text`,text:JSON.stringify({traceId:e.traceId,count:t.length,timeline:t.map(e=>({timestamp:e.timestamp.toISOString(),service:e.service,spanId:e.spanId,parentSpanId:e.parentSpanId,level:e.level,message:e.message,duration:e.duration}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting trace timeline: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},q=class e{static TOOL_NAME=`query_logs`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getDefinition(){return{name:e.TOOL_NAME,description:`Query and filter log entries by level, trace ID, time range, service, or other criteria. Returns filtered log entries with full metadata.`,inputSchema:{type:`object`,properties:{level:{oneOf:[{type:`string`,enum:[`trace`,`debug`,`info`,`warn`,`error`,`fatal`]},{type:`array`,items:{type:`string`,enum:[`trace`,`debug`,`info`,`warn`,`error`,`fatal`]}}],description:`Log level(s) to filter by`},traceId:{type:`string`,description:`Trace ID to filter by (OTEL format: 32 hex characters)`},service:{oneOf:[{type:`string`},{type:`array`,items:{type:`string`}}],description:`Service name(s) to filter by`},startTime:{type:`string`,format:`date-time`,description:`Start time for log range (ISO 8601 format)`},endTime:{type:`string`,format:`date-time`,description:`End time for log range (ISO 8601 format)`},limit:{type:`number`,minimum:1,maximum:1e3,default:100,description:`Maximum number of log entries to return`}},additionalProperties:!1}}}async execute(e){try{let t=e.limit??100,n;if(e.traceId)n=await this.queryService.filterByTrace(e.traceId),n=n.slice(0,t);else if(e.level)n=await this.queryService.filterByLevel(e.level,t);else if(e.service)n=await this.queryService.filterByService(e.service),n=n.slice(0,t);else if(e.startTime||e.endTime){let r=e.startTime?new Date(e.startTime):new Date(0),i=e.endTime?new Date(e.endTime):new Date;n=await this.queryService.filterByTimeRange(r,i),n=n.slice(0,t)}else n=await this.queryService.filterByLevel([`info`,`warn`,`error`,`fatal`],t);return{content:[{type:`text`,text:JSON.stringify({count:n.length,logs:n.map(e=>({id:e.id,timestamp:e.timestamp.toISOString(),level:e.level,message:e.message,service:e.service,traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId,hostname:e.hostname,pid:e.pid,metadata:e.metadata,errorType:e.errorType,errorMessage:e.errorMessage,errorStack:e.errorStack}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error querying logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},J=class e{static TOOL_NAME=`search_logs`;searchService;semanticSearchService;constructor(e){this.searchService=e.get(y.LogSearchService),this.semanticSearchService=e.get(y.SemanticSearchService)}getDefinition(){return{name:e.TOOL_NAME,description:`Search log entries using FTS5, local semantic embeddings, or both. Hybrid mode combines exact text and semantic similarity for better incident retrieval.`,inputSchema:{type:`object`,properties:{searchQuery:{type:`string`,description:`FTS5 search query (supports phrase queries with quotes, prefix matching with *, boolean operators AND/OR/NOT)`},mode:{type:`string`,enum:[`fts`,`semantic`,`hybrid`],default:`hybrid`,description:`Search strategy to use`},service:{oneOf:[{type:`string`},{type:`array`,items:{type:`string`}}],description:`Service name(s) to filter by`},level:{oneOf:[{type:`string`,enum:[`trace`,`debug`,`info`,`warn`,`error`,`fatal`]},{type:`array`,items:{type:`string`,enum:[`trace`,`debug`,`info`,`warn`,`error`,`fatal`]}}],description:`Log level(s) to filter by`},startTime:{type:`string`,format:`date-time`,description:`Start time for log range (ISO 8601 format)`},endTime:{type:`string`,format:`date-time`,description:`End time for log range (ISO 8601 format)`},limit:{type:`number`,minimum:1,maximum:1e3,default:100,description:`Maximum number of search results to return`}},required:[`searchQuery`],additionalProperties:!1}}}async execute(e){try{let t={},n=e.mode??`hybrid`;e.service&&(t.service=e.service),e.level&&(t.level=e.level),e.startTime&&(t.startTime=new Date(e.startTime)),e.endTime&&(t.endTime=new Date(e.endTime));let r=e.limit??100,i=n===`semantic`?await this.semanticSearchService.searchLogs(e.searchQuery,t,r):n===`fts`?await this.searchService.searchLogs(e.searchQuery,t,r):await this.searchHybrid(e.searchQuery,t,r);return{content:[{type:`text`,text:JSON.stringify({mode:n,count:i.length,query:e.searchQuery,results:i.map(e=>({score:`score`in e?e.score:this.getFallbackScore(e.rank),rank:`rank`in e?e.rank:void 0,distance:`distance`in e?e.distance:void 0,sources:`sources`in e?e.sources:void 0,id:e.id,timestamp:e.timestamp.toISOString(),level:e.level,message:e.message,service:e.service,traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId,hostname:e.hostname,pid:e.pid,metadata:e.metadata,errorType:e.errorType,errorMessage:e.errorMessage}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error searching logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}getFallbackScore(e){return 1/(1+Math.max(0,Math.abs(e)))}async searchHybrid(e,t,n){let r=Math.max(n*2,50),i=this.searchService.searchLogs(e,t,r),a=await this.semanticSearchService.isAvailable(),o=await i;if(!a)return o;let s=await this.semanticSearchService.searchLogs(e,t,r),c=new Map;return o.forEach((e,t)=>{c.set(e.id,{result:e,score:.65*(1/(1+t)),rank:e.rank,sources:new Set([`fts`])})}),s.forEach((e,t)=>{let n=c.get(e.id),r=.35*(1/(1+t));n?(n.score+=r,n.sources.add(`semantic`),n.distance=e.distance,n.rank===void 0&&`rank`in e&&(n.rank=e.rank),n.result={...n.result,...e}):c.set(e.id,{result:e,score:r,distance:e.distance,sources:new Set([`semantic`])})}),Array.from(c.values()).sort((e,t)=>t.score-e.score).slice(0,n).map(e=>({...e.result,score:e.score,sources:Array.from(e.sources),rank:e.rank,distance:e.distance}))}};function Y(e){let t=new m.Server({name:`log-sink-mcp`,version:`0.1.0`},{capabilities:{tools:{}}}),n=e??V(),r=new q(n),i=new J(n),a=new K(n),o=new H(n),s=new W(n),c=new G(n),l=new U(n);return t.setRequestHandler(h.ListToolsRequestSchema,async()=>({tools:[r.getDefinition(),i.getDefinition(),a.getDefinition(),o.getDefinition(),s.getDefinition(),c.getDefinition(),l.getDefinition()]})),t.setRequestHandler(h.CallToolRequestSchema,async e=>{let{name:t,arguments:n}=e.params;try{switch(t){case`query_logs`:return await r.execute(n);case`search_logs`:return await i.execute(n);case`get_trace_timeline`:return await a.execute(n);case`analyze_errors`:return await o.execute(n);case`get_log_stats`:return await s.execute(n);case`get_services`:return await c.execute(n);case`clear_logs`:return await l.execute(n);default:throw Error(`Unknown tool: ${t}`)}}catch(e){return{content:[{type:`text`,text:`Error executing tool ${t}: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}}),t}var X=class{server;transport=null;constructor(e){this.server=e}async start(){this.transport=new g.StdioServerTransport,await this.server.connect(this.transport)}async stop(){this.transport&&=(await this.transport.close(),null)}};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return U}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return G}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return J}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return X}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return V}});
|
|
245
|
+
//# sourceMappingURL=stdio-D-S2Mhwk.cjs.map
|