@schmitech/chatbot-api 0.5.1 → 0.5.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/dist/api.cjs +2 -2
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.ts +9 -31
- package/dist/api.mjs +90 -119
- package/dist/api.mjs.map +1 -1
- package/package.json +2 -1
package/dist/api.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`,
|
|
1
|
+
"use strict";var S=Object.create;var p=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var T=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var K=(t,e,r)=>e in t?p(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var D=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of P(e))!O.call(t,n)&&n!==r&&p(t,n,{get:()=>e[n],enumerable:!(s=x(e,n))||s.enumerable});return t};var I=(t,e,r)=>(r=t!=null?S(T(t)):{},D(e||!t||!t.__esModule?p(r,"default",{value:t,enumerable:!0}):r,t));var f=(t,e,r)=>K(t,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let m=null,v=null;typeof window>"u"&&Promise.all([import("http").catch(()=>null),import("https").catch(()=>null)]).then(([t,e])=>{var r,s;(r=t==null?void 0:t.default)!=null&&r.Agent?m=new t.default.Agent({keepAlive:!0}):t!=null&&t.Agent&&(m=new t.Agent({keepAlive:!0})),(s=e==null?void 0:e.default)!=null&&s.Agent?v=new e.default.Agent({keepAlive:!0}):e!=null&&e.Agent&&(v=new e.Agent({keepAlive:!0}))}).catch(t=>{console.warn("Failed to initialize HTTP agents:",t.message)});class E{constructor(e){f(this,"apiUrl");f(this,"apiKey");f(this,"sessionId");if(!e.apiUrl||typeof e.apiUrl!="string")throw new Error("API URL must be a valid string");if(e.apiKey!==void 0&&e.apiKey!==null&&typeof e.apiKey!="string")throw new Error("API key must be a valid string or null");if(e.sessionId!==void 0&&e.sessionId!==null&&typeof e.sessionId!="string")throw new Error("Session ID must be a valid string or null");this.apiUrl=e.apiUrl,this.apiKey=e.apiKey??null,this.sessionId=e.sessionId??null}setSessionId(e){if(e!==null&&typeof e!="string")throw new Error("Session ID must be a valid string or null");this.sessionId=e}getSessionId(){return this.sessionId}getFetchOptions(e={}){const r={};if(typeof window>"u"){const c=this.apiUrl.startsWith("https:")?v:m;c&&(r.agent=c)}else r.headers={Connection:"keep-alive"};const s={"X-Request-ID":Date.now().toString(36)+Math.random().toString(36).substring(2)};return r.headers&&Object.assign(s,r.headers),e.headers&&Object.assign(s,e.headers),this.apiKey&&(s["X-API-Key"]=this.apiKey),this.sessionId&&(s["X-Session-ID"]=this.sessionId),{...e,...r,headers:s}}createChatRequest(e,r=!0){return{messages:[{role:"user",content:e}],stream:r}}async*streamChat(e,r=!0){var s;try{const n=new AbortController,c=setTimeout(()=>n.abort(),6e4),a=await fetch(`${this.apiUrl}/v1/chat`,{...this.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json",Accept:r?"text/event-stream":"application/json"},body:JSON.stringify(this.createChatRequest(e,r))}),signal:n.signal});if(clearTimeout(c),!a.ok){const l=await a.text();throw new Error(`Network response was not ok: ${a.status} ${l}`)}if(!r){const l=await a.json();l.response&&(yield{text:l.response,done:!0});return}const w=(s=a.body)==null?void 0:s.getReader();if(!w)throw new Error("No reader available");const b=new TextDecoder;let i="",y=!1;try{for(;;){const{done:l,value:k}=await w.read();if(l)break;const C=b.decode(k,{stream:!0});i+=C;let u=0,g;for(;(g=i.indexOf(`
|
|
2
|
+
`,u))!==-1;){const d=i.slice(u,g).trim();if(u=g+1,d&&d.startsWith("data: ")){const h=d.slice(6).trim();if(!h||h==="[DONE]"){yield{text:"",done:!0};return}try{const o=JSON.parse(h);if(o.error)throw new Error(`Server Error: ${o.error.message}`);if(o.response&&(y=!0,yield{text:o.response,done:o.done||!1}),o.done){yield{text:"",done:!0};return}}catch(o){console.warn("Error parsing JSON chunk:",o,"Chunk:",h)}}else d&&(y=!0,yield{text:d,done:!1})}i=i.slice(u),i.length>1e6&&(console.warn("Buffer too large, truncating..."),i=i.slice(-5e5))}y&&(yield{text:"",done:!0})}finally{w.releaseLock()}}catch(n){throw n.name==="AbortError"?new Error("Connection timed out. Please check if the server is running."):n.name==="TypeError"&&n.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):n}}async clearConversationHistory(e){const r=e||this.sessionId;if(!r)throw new Error("No session ID provided and no current session available");if(!this.apiKey)throw new Error("API key is required for clearing conversation history");const s={"Content-Type":"application/json","X-Session-ID":r,"X-API-Key":this.apiKey};try{const n=await fetch(`${this.apiUrl}/admin/chat-history/${r}`,{...this.getFetchOptions({method:"DELETE",headers:s})});if(!n.ok){const a=await n.text();throw new Error(`Failed to clear conversation history: ${n.status} ${a}`)}return await n.json()}catch(n){throw n.name==="TypeError"&&n.message.includes("Failed to fetch")?new Error("Could not connect to the server. Please check if the server is running."):n}}}let A=null;const U=(t,e=null,r=null)=>{A=new E({apiUrl:t,apiKey:e,sessionId:r})};async function*j(t,e=!0){if(!A)throw new Error("API not configured. Please call configureApi() with your server URL before using any API functions.");yield*A.streamChat(t,e)}exports.ApiClient=E;exports.configureApi=U;exports.streamChat=j;
|
|
3
3
|
//# sourceMappingURL=api.cjs.map
|
package/dist/api.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.cjs","sources":["../api.ts"],"sourcesContent":["// For Node.js environments, we can use http.Agent for connection pooling\nlet httpAgent: any = null;\nlet httpsAgent: any = null;\n\n// Initialize agents for connection pooling in Node.js environments\nif (typeof window === 'undefined') {\n // Lazy load to avoid including 'http' in browser bundles\n Promise.all([\n import('http').catch(() => null),\n import('https').catch(() => null)\n ]).then(([http, https]) => {\n if (http?.default?.Agent) {\n httpAgent = new http.default.Agent({ keepAlive: true });\n } else if (http?.Agent) {\n httpAgent = new http.Agent({ keepAlive: true });\n }\n \n if (https?.default?.Agent) {\n httpsAgent = new https.default.Agent({ keepAlive: true });\n } else if (https?.Agent) {\n httpsAgent = new https.Agent({ keepAlive: true });\n }\n }).catch(err => {\n // Silently fail - connection pooling is optional\n console.warn('Failed to initialize HTTP agents:', err.message);\n });\n}\n\n// Define the StreamResponse interface\nexport interface StreamResponse {\n text: string;\n done: boolean;\n}\n\nexport interface ChatResponse {\n response: string;\n}\n\n// MCP Protocol interfaces\ninterface MCPRequest {\n jsonrpc: \"2.0\";\n method: string;\n params: {\n name: string;\n arguments: {\n messages?: Array<{\n role: string;\n content: string;\n }>;\n stream?: boolean;\n tools?: Array<{\n name: string;\n parameters: Record<string, any>;\n }>;\n };\n };\n id: string;\n}\n\ninterface MCPResponse {\n jsonrpc: \"2.0\";\n id: string;\n result?: {\n type?: \"start\" | \"chunk\" | \"complete\";\n chunk?: {\n content: string;\n };\n output?: {\n messages: Array<{\n role: string;\n content: string;\n }>;\n };\n };\n error?: {\n code: number;\n message: string;\n };\n}\n\nexport class ApiClient {\n private readonly apiUrl: string;\n private readonly apiKey: string | null;\n private sessionId: string | null; // Session ID can be mutable\n\n constructor(config: { apiUrl: string; apiKey?: string | null; sessionId?: string | null }) {\n if (!config.apiUrl || typeof config.apiUrl !== 'string') {\n throw new Error('API URL must be a valid string');\n }\n if (config.apiKey !== undefined && config.apiKey !== null && typeof config.apiKey !== 'string') {\n throw new Error('API key must be a valid string or null');\n }\n if (config.sessionId !== undefined && config.sessionId !== null && typeof config.sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n \n this.apiUrl = config.apiUrl;\n this.apiKey = config.apiKey ?? null;\n this.sessionId = config.sessionId ?? null;\n }\n\n public setSessionId(sessionId: string | null): void {\n if (sessionId !== null && typeof sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n this.sessionId = sessionId;\n }\n\n public getSessionId(): string | null {\n return this.sessionId;\n }\n\n // Helper to get fetch options with connection pooling if available\n private getFetchOptions(options: RequestInit = {}): RequestInit {\n const baseOptions: RequestInit = {};\n \n // Environment-specific options\n if (typeof window === 'undefined') {\n // Node.js: Use connection pooling agent\n const isHttps = this.apiUrl.startsWith('https:');\n const agent = isHttps ? httpsAgent : httpAgent;\n if (agent) {\n (baseOptions as any).agent = agent;\n }\n } else {\n // Browser: Use keep-alive header\n baseOptions.headers = { 'Connection': 'keep-alive' };\n }\n\n // Common headers\n const headers: Record<string, string> = {\n 'X-Request-ID': Date.now().toString(36) + Math.random().toString(36).substring(2),\n };\n\n // Merge base options headers (for browser keep-alive)\n if (baseOptions.headers) {\n Object.assign(headers, baseOptions.headers);\n }\n\n // Merge original request headers\n if (options.headers) {\n Object.assign(headers, options.headers);\n }\n\n if (this.apiKey) {\n headers['X-API-Key'] = this.apiKey;\n }\n\n if (this.sessionId) {\n headers['X-Session-ID'] = this.sessionId;\n }\n\n return {\n ...options,\n ...baseOptions,\n headers,\n };\n }\n\n // Create MCP request\n private createMCPRequest(message: string, stream: boolean = true): MCPRequest {\n return {\n jsonrpc: \"2.0\",\n method: \"tools/call\",\n params: {\n name: \"chat\",\n arguments: {\n messages: [\n { role: \"user\", content: message }\n ],\n stream\n }\n },\n id: Date.now().toString(36) + Math.random().toString(36).substring(2)\n };\n }\n\n // Create MCP tools request\n private createMCPToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): MCPRequest {\n return {\n jsonrpc: \"2.0\",\n method: \"tools/call\",\n params: {\n name: \"tools\",\n arguments: {\n tools\n }\n },\n id: Date.now().toString(36) + Math.random().toString(36).substring(2)\n };\n }\n\n public async *streamChat(\n message: string,\n stream: boolean = true\n ): AsyncGenerator<StreamResponse> {\n try {\n // Add timeout to the fetch request\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 60000); // 60 second timeout\n\n const response = await fetch(`${this.apiUrl}/v1/chat`, {\n ...this.getFetchOptions({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': stream ? 'text/event-stream' : 'application/json'\n },\n body: JSON.stringify(this.createMCPRequest(message, stream)),\n }),\n signal: controller.signal\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Network response was not ok: ${response.status} ${errorText}`);\n }\n\n if (!stream) {\n // Handle non-streaming response\n const data = await response.json() as MCPResponse;\n if (data.error) {\n throw new Error(`MCP Error: ${data.error.message}`);\n }\n if (data.result?.output?.messages?.[0]?.content) {\n yield {\n text: data.result.output.messages[0].content,\n done: true\n };\n }\n return;\n }\n \n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader available');\n\n const decoder = new TextDecoder();\n let buffer = '';\n let hasReceivedContent = false;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n const chunk = decoder.decode(value, { stream: true });\n buffer += chunk;\n \n // Process complete lines immediately as they arrive\n let lineStartIndex = 0;\n let newlineIndex;\n \n while ((newlineIndex = buffer.indexOf('\\n', lineStartIndex)) !== -1) {\n const line = buffer.slice(lineStartIndex, newlineIndex).trim();\n lineStartIndex = newlineIndex + 1;\n \n if (line && line.startsWith('data: ')) {\n const jsonText = line.slice(6).trim();\n \n // Check for [DONE] message or empty data lines\n if (!jsonText || jsonText === '[DONE]') {\n yield { text: '', done: true };\n return;\n }\n\n try {\n const data = JSON.parse(jsonText) as MCPResponse;\n \n if (data.error) {\n throw new Error(`MCP Error: ${data.error.message}`);\n }\n \n // Handle MCP protocol format - server sends chunks of new text directly\n if (data.result?.type === 'chunk' && data.result.chunk?.content) {\n hasReceivedContent = true;\n yield { text: data.result.chunk.content, done: false };\n } else if (data.result?.type === 'complete') {\n // Final piece of content or just the done signal\n const finalText = data.result.output?.messages?.[0]?.content ?? '';\n // Only yield final text if we haven't received incremental chunks\n if (!hasReceivedContent && finalText) {\n yield { text: finalText, done: true };\n } else {\n yield { text: '', done: true };\n }\n return;\n } else if ('response' in data && typeof data.response === 'string') {\n // Handle direct server response format (legacy compatibility)\n const isDone = 'done' in data && data.done === true;\n \n if (isDone) {\n // For final response, only yield if we haven't received incremental chunks\n if (!hasReceivedContent && data.response) {\n yield { text: data.response, done: true };\n } else {\n yield { text: '', done: true };\n }\n return;\n } else {\n // For incremental chunks, always yield\n hasReceivedContent = true;\n yield { text: data.response, done: false };\n }\n }\n \n } catch (parseError) {\n console.warn('Error parsing JSON chunk:', parseError);\n }\n }\n }\n \n // Keep remaining incomplete line in buffer\n buffer = buffer.slice(lineStartIndex);\n \n // Prevent buffer from growing too large\n if (buffer.length > 1000000) { // 1MB limit\n console.warn('Buffer too large, truncating...');\n buffer = buffer.slice(-500000); // Keep last 500KB\n }\n }\n \n // If we exit the while loop naturally, ensure we send a done signal\n if (hasReceivedContent) {\n yield { text: '', done: true };\n }\n \n } finally {\n reader.releaseLock();\n }\n \n } catch (error: any) {\n if (error.name === 'AbortError') {\n throw new Error('Connection timed out. Please check if the server is running.');\n } else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n throw new Error('Could not connect to the server. Please check if the server is running.');\n } else {\n // Re-throw the error to be caught by the caller\n throw error;\n }\n }\n }\n\n // New function to send tools request\n public async sendToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): Promise<MCPResponse> {\n const response = await fetch(`${this.apiUrl}/v1/chat`, this.getFetchOptions({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(this.createMCPToolsRequest(tools)),\n }));\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Network response was not ok: ${response.status} ${errorText}`);\n }\n\n const data = await response.json() as MCPResponse;\n if (data.error) {\n throw new Error(`MCP Error: ${data.error.message}`);\n }\n\n return data;\n }\n}\n\n// Legacy compatibility functions - these create a default client instance\n// These are kept for backward compatibility but should be deprecated in favor of the class-based approach\n\nlet defaultClient: ApiClient | null = null;\n\n// Configure the API with a custom URL, API key (optional), and session ID (optional)\nexport const configureApi = (apiUrl: string, apiKey: string | null = null, sessionId: string | null = null): void => {\n defaultClient = new ApiClient({ apiUrl, apiKey, sessionId });\n}\n\n// Legacy streamChat function that uses the default client\nexport async function* streamChat(\n message: string,\n stream: boolean = true\n): AsyncGenerator<StreamResponse> {\n if (!defaultClient) {\n throw new Error('API not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n \n yield* defaultClient.streamChat(message, stream);\n}\n\n// Legacy sendToolsRequest function that uses the default client\nexport async function sendToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): Promise<MCPResponse> {\n if (!defaultClient) {\n throw new Error('API not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n \n return defaultClient.sendToolsRequest(tools);\n}"],"names":["httpAgent","httpsAgent","http","https","_a","_b","err","ApiClient","config","__publicField","sessionId","options","baseOptions","agent","headers","message","stream","tools","controller","timeoutId","response","errorText","data","_d","_c","reader","_e","decoder","buffer","hasReceivedContent","done","value","chunk","lineStartIndex","newlineIndex","line","jsonText","_f","_g","_h","finalText","_k","_j","_i","parseError","error","defaultClient","configureApi","apiUrl","apiKey","streamChat","sendToolsRequest"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.cjs","sources":["../api.ts"],"sourcesContent":["// For Node.js environments, we can use http.Agent for connection pooling\nlet httpAgent: any = null;\nlet httpsAgent: any = null;\n\n// Initialize agents for connection pooling in Node.js environments\nif (typeof window === 'undefined') {\n // Lazy load to avoid including 'http' in browser bundles\n Promise.all([\n import('http').catch(() => null),\n import('https').catch(() => null)\n ]).then(([http, https]) => {\n if (http?.default?.Agent) {\n httpAgent = new http.default.Agent({ keepAlive: true });\n } else if (http?.Agent) {\n httpAgent = new http.Agent({ keepAlive: true });\n }\n \n if (https?.default?.Agent) {\n httpsAgent = new https.default.Agent({ keepAlive: true });\n } else if (https?.Agent) {\n httpsAgent = new https.Agent({ keepAlive: true });\n }\n }).catch(err => {\n // Silently fail - connection pooling is optional\n console.warn('Failed to initialize HTTP agents:', err.message);\n });\n}\n\n// Define the StreamResponse interface\nexport interface StreamResponse {\n text: string;\n done: boolean;\n}\n\n// The server now returns this directly for non-streaming chat\nexport interface ChatResponse {\n response: string;\n sources?: any[];\n}\n\n// The request body for the /v1/chat endpoint\ninterface ChatRequest {\n messages: Array<{ role: string; content: string; }>;\n stream: boolean;\n}\n\nexport class ApiClient {\n private readonly apiUrl: string;\n private readonly apiKey: string | null;\n private sessionId: string | null; // Session ID can be mutable\n\n constructor(config: { apiUrl: string; apiKey?: string | null; sessionId?: string | null }) {\n if (!config.apiUrl || typeof config.apiUrl !== 'string') {\n throw new Error('API URL must be a valid string');\n }\n if (config.apiKey !== undefined && config.apiKey !== null && typeof config.apiKey !== 'string') {\n throw new Error('API key must be a valid string or null');\n }\n if (config.sessionId !== undefined && config.sessionId !== null && typeof config.sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n \n this.apiUrl = config.apiUrl;\n this.apiKey = config.apiKey ?? null;\n this.sessionId = config.sessionId ?? null;\n }\n\n public setSessionId(sessionId: string | null): void {\n if (sessionId !== null && typeof sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n this.sessionId = sessionId;\n }\n\n public getSessionId(): string | null {\n return this.sessionId;\n }\n\n // Helper to get fetch options with connection pooling if available\n private getFetchOptions(options: RequestInit = {}): RequestInit {\n const baseOptions: RequestInit = {};\n \n // Environment-specific options\n if (typeof window === 'undefined') {\n // Node.js: Use connection pooling agent\n const isHttps = this.apiUrl.startsWith('https:');\n const agent = isHttps ? httpsAgent : httpAgent;\n if (agent) {\n (baseOptions as any).agent = agent;\n }\n } else {\n // Browser: Use keep-alive header\n baseOptions.headers = { 'Connection': 'keep-alive' };\n }\n\n // Common headers\n const headers: Record<string, string> = {\n 'X-Request-ID': Date.now().toString(36) + Math.random().toString(36).substring(2),\n };\n\n // Merge base options headers (for browser keep-alive)\n if (baseOptions.headers) {\n Object.assign(headers, baseOptions.headers);\n }\n\n // Merge original request headers\n if (options.headers) {\n Object.assign(headers, options.headers);\n }\n\n if (this.apiKey) {\n headers['X-API-Key'] = this.apiKey;\n }\n\n if (this.sessionId) {\n headers['X-Session-ID'] = this.sessionId;\n }\n\n return {\n ...options,\n ...baseOptions,\n headers,\n };\n }\n\n // Create Chat request\n private createChatRequest(message: string, stream: boolean = true): ChatRequest {\n return {\n messages: [\n { role: \"user\", content: message }\n ],\n stream\n };\n }\n\n public async *streamChat(\n message: string,\n stream: boolean = true\n ): AsyncGenerator<StreamResponse> {\n try {\n // Add timeout to the fetch request\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 60000); // 60 second timeout\n\n const response = await fetch(`${this.apiUrl}/v1/chat`, {\n ...this.getFetchOptions({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': stream ? 'text/event-stream' : 'application/json'\n },\n body: JSON.stringify(this.createChatRequest(message, stream)),\n }),\n signal: controller.signal\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Network response was not ok: ${response.status} ${errorText}`);\n }\n\n if (!stream) {\n // Handle non-streaming response\n const data = await response.json() as ChatResponse;\n if (data.response) {\n yield {\n text: data.response,\n done: true\n };\n }\n return;\n }\n \n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader available');\n\n const decoder = new TextDecoder();\n let buffer = '';\n let hasReceivedContent = false;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n const chunk = decoder.decode(value, { stream: true });\n buffer += chunk;\n \n // Process complete lines immediately as they arrive\n let lineStartIndex = 0;\n let newlineIndex;\n \n while ((newlineIndex = buffer.indexOf('\\n', lineStartIndex)) !== -1) {\n const line = buffer.slice(lineStartIndex, newlineIndex).trim();\n lineStartIndex = newlineIndex + 1;\n \n if (line && line.startsWith('data: ')) {\n const jsonText = line.slice(6).trim();\n \n if (!jsonText || jsonText === '[DONE]') {\n yield { text: '', done: true };\n return;\n }\n\n try {\n const data = JSON.parse(jsonText);\n \n if (data.error) {\n throw new Error(`Server Error: ${data.error.message}`);\n }\n \n if (data.response) {\n hasReceivedContent = true;\n yield { text: data.response, done: data.done || false };\n }\n\n if (data.done) {\n yield { text: '', done: true };\n return;\n }\n \n } catch (parseError) {\n console.warn('Error parsing JSON chunk:', parseError, 'Chunk:', jsonText);\n }\n } else if (line) {\n // Handle raw text chunks that are not in SSE format\n hasReceivedContent = true;\n yield { text: line, done: false };\n }\n }\n \n buffer = buffer.slice(lineStartIndex);\n \n if (buffer.length > 1000000) { // 1MB limit\n console.warn('Buffer too large, truncating...');\n buffer = buffer.slice(-500000); // Keep last 500KB\n }\n }\n \n if (hasReceivedContent) {\n yield { text: '', done: true };\n }\n \n } finally {\n reader.releaseLock();\n }\n \n } catch (error: any) {\n if (error.name === 'AbortError') {\n throw new Error('Connection timed out. Please check if the server is running.');\n } else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n throw new Error('Could not connect to the server. Please check if the server is running.');\n } else {\n throw error;\n }\n }\n }\n\n public async clearConversationHistory(sessionId?: string): Promise<{\n status: string;\n message: string;\n session_id: string;\n deleted_count: number;\n timestamp: string;\n }> {\n /**\n * Clear conversation history for a session.\n * \n * @param sessionId - Optional session ID to clear. If not provided, uses current session.\n * @returns Promise resolving to operation result\n * @throws Error if the operation fails\n */\n const targetSessionId = sessionId || this.sessionId;\n \n if (!targetSessionId) {\n throw new Error('No session ID provided and no current session available');\n }\n \n if (!this.apiKey) {\n throw new Error('API key is required for clearing conversation history');\n }\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Session-ID': targetSessionId,\n 'X-API-Key': this.apiKey\n };\n \n try {\n const response = await fetch(`${this.apiUrl}/admin/chat-history/${targetSessionId}`, {\n ...this.getFetchOptions({\n method: 'DELETE',\n headers\n })\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to clear conversation history: ${response.status} ${errorText}`);\n }\n \n const result = await response.json();\n return result;\n \n } catch (error: any) {\n if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n throw new Error('Could not connect to the server. Please check if the server is running.');\n } else {\n throw error;\n }\n }\n }\n}\n\n// Legacy compatibility functions - these create a default client instance\n// These are kept for backward compatibility but should be deprecated in favor of the class-based approach\n\nlet defaultClient: ApiClient | null = null;\n\n// Configure the API with a custom URL, API key (optional), and session ID (optional)\nexport const configureApi = (apiUrl: string, apiKey: string | null = null, sessionId: string | null = null): void => {\n defaultClient = new ApiClient({ apiUrl, apiKey, sessionId });\n}\n\n// Legacy streamChat function that uses the default client\nexport async function* streamChat(\n message: string,\n stream: boolean = true\n): AsyncGenerator<StreamResponse> {\n if (!defaultClient) {\n throw new Error('API not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n \n yield* defaultClient.streamChat(message, stream);\n}\n\n"],"names":["httpAgent","httpsAgent","http","https","_a","_b","err","ApiClient","config","__publicField","sessionId","options","baseOptions","agent","headers","message","stream","controller","timeoutId","response","errorText","data","reader","decoder","buffer","hasReceivedContent","done","value","chunk","lineStartIndex","newlineIndex","line","jsonText","parseError","error","targetSessionId","defaultClient","configureApi","apiUrl","apiKey","streamChat"],"mappings":"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"}
|
package/dist/api.d.ts
CHANGED
|
@@ -4,26 +4,7 @@ export interface StreamResponse {
|
|
|
4
4
|
}
|
|
5
5
|
export interface ChatResponse {
|
|
6
6
|
response: string;
|
|
7
|
-
|
|
8
|
-
interface MCPResponse {
|
|
9
|
-
jsonrpc: "2.0";
|
|
10
|
-
id: string;
|
|
11
|
-
result?: {
|
|
12
|
-
type?: "start" | "chunk" | "complete";
|
|
13
|
-
chunk?: {
|
|
14
|
-
content: string;
|
|
15
|
-
};
|
|
16
|
-
output?: {
|
|
17
|
-
messages: Array<{
|
|
18
|
-
role: string;
|
|
19
|
-
content: string;
|
|
20
|
-
}>;
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
error?: {
|
|
24
|
-
code: number;
|
|
25
|
-
message: string;
|
|
26
|
-
};
|
|
7
|
+
sources?: any[];
|
|
27
8
|
}
|
|
28
9
|
export declare class ApiClient {
|
|
29
10
|
private readonly apiUrl;
|
|
@@ -37,18 +18,15 @@ export declare class ApiClient {
|
|
|
37
18
|
setSessionId(sessionId: string | null): void;
|
|
38
19
|
getSessionId(): string | null;
|
|
39
20
|
private getFetchOptions;
|
|
40
|
-
private
|
|
41
|
-
private createMCPToolsRequest;
|
|
21
|
+
private createChatRequest;
|
|
42
22
|
streamChat(message: string, stream?: boolean): AsyncGenerator<StreamResponse>;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
23
|
+
clearConversationHistory(sessionId?: string): Promise<{
|
|
24
|
+
status: string;
|
|
25
|
+
message: string;
|
|
26
|
+
session_id: string;
|
|
27
|
+
deleted_count: number;
|
|
28
|
+
timestamp: string;
|
|
29
|
+
}>;
|
|
47
30
|
}
|
|
48
31
|
export declare const configureApi: (apiUrl: string, apiKey?: string | null, sessionId?: string | null) => void;
|
|
49
32
|
export declare function streamChat(message: string, stream?: boolean): AsyncGenerator<StreamResponse>;
|
|
50
|
-
export declare function sendToolsRequest(tools: Array<{
|
|
51
|
-
name: string;
|
|
52
|
-
parameters: Record<string, any>;
|
|
53
|
-
}>): Promise<MCPResponse>;
|
|
54
|
-
export {};
|
package/dist/api.mjs
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
let
|
|
1
|
+
var k = Object.defineProperty;
|
|
2
|
+
var b = (r, e, t) => e in r ? k(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
3
|
+
var f = (r, e, t) => b(r, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
let p = null, m = null;
|
|
5
5
|
typeof window > "u" && Promise.all([
|
|
6
6
|
import("http").catch(() => null),
|
|
7
7
|
import("https").catch(() => null)
|
|
8
8
|
]).then(([r, e]) => {
|
|
9
9
|
var t, s;
|
|
10
|
-
(t = r == null ? void 0 : r.default) != null && t.Agent ?
|
|
10
|
+
(t = r == null ? void 0 : r.default) != null && t.Agent ? p = new r.default.Agent({ keepAlive: !0 }) : r != null && r.Agent && (p = new r.Agent({ keepAlive: !0 })), (s = e == null ? void 0 : e.default) != null && s.Agent ? m = new e.default.Agent({ keepAlive: !0 }) : e != null && e.Agent && (m = new e.Agent({ keepAlive: !0 }));
|
|
11
11
|
}).catch((r) => {
|
|
12
12
|
console.warn("Failed to initialize HTTP agents:", r.message);
|
|
13
13
|
});
|
|
14
|
-
class
|
|
14
|
+
class x {
|
|
15
15
|
// Session ID can be mutable
|
|
16
16
|
constructor(e) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
f(this, "apiUrl");
|
|
18
|
+
f(this, "apiKey");
|
|
19
|
+
f(this, "sessionId");
|
|
20
20
|
if (!e.apiUrl || typeof e.apiUrl != "string")
|
|
21
21
|
throw new Error("API URL must be a valid string");
|
|
22
22
|
if (e.apiKey !== void 0 && e.apiKey !== null && typeof e.apiKey != "string")
|
|
@@ -37,8 +37,8 @@ class K {
|
|
|
37
37
|
getFetchOptions(e = {}) {
|
|
38
38
|
const t = {};
|
|
39
39
|
if (typeof window > "u") {
|
|
40
|
-
const
|
|
41
|
-
|
|
40
|
+
const c = this.apiUrl.startsWith("https:") ? m : p;
|
|
41
|
+
c && (t.agent = c);
|
|
42
42
|
} else
|
|
43
43
|
t.headers = { Connection: "keep-alive" };
|
|
44
44
|
const s = {
|
|
@@ -50,154 +50,125 @@ class K {
|
|
|
50
50
|
headers: s
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
// Create
|
|
54
|
-
|
|
53
|
+
// Create Chat request
|
|
54
|
+
createChatRequest(e, t = !0) {
|
|
55
55
|
return {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
arguments: {
|
|
61
|
-
messages: [
|
|
62
|
-
{ role: "user", content: e }
|
|
63
|
-
],
|
|
64
|
-
stream: t
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
id: Date.now().toString(36) + Math.random().toString(36).substring(2)
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
// Create MCP tools request
|
|
71
|
-
createMCPToolsRequest(e) {
|
|
72
|
-
return {
|
|
73
|
-
jsonrpc: "2.0",
|
|
74
|
-
method: "tools/call",
|
|
75
|
-
params: {
|
|
76
|
-
name: "tools",
|
|
77
|
-
arguments: {
|
|
78
|
-
tools: e
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
id: Date.now().toString(36) + Math.random().toString(36).substring(2)
|
|
56
|
+
messages: [
|
|
57
|
+
{ role: "user", content: e }
|
|
58
|
+
],
|
|
59
|
+
stream: t
|
|
82
60
|
};
|
|
83
61
|
}
|
|
84
62
|
async *streamChat(e, t = !0) {
|
|
85
|
-
var s
|
|
63
|
+
var s;
|
|
86
64
|
try {
|
|
87
|
-
const
|
|
65
|
+
const n = new AbortController(), c = setTimeout(() => n.abort(), 6e4), a = await fetch(`${this.apiUrl}/v1/chat`, {
|
|
88
66
|
...this.getFetchOptions({
|
|
89
67
|
method: "POST",
|
|
90
68
|
headers: {
|
|
91
69
|
"Content-Type": "application/json",
|
|
92
70
|
Accept: t ? "text/event-stream" : "application/json"
|
|
93
71
|
},
|
|
94
|
-
body: JSON.stringify(this.
|
|
72
|
+
body: JSON.stringify(this.createChatRequest(e, t))
|
|
95
73
|
}),
|
|
96
|
-
signal:
|
|
74
|
+
signal: n.signal
|
|
97
75
|
});
|
|
98
|
-
if (clearTimeout(
|
|
99
|
-
const
|
|
100
|
-
throw new Error(`Network response was not ok: ${
|
|
76
|
+
if (clearTimeout(c), !a.ok) {
|
|
77
|
+
const l = await a.text();
|
|
78
|
+
throw new Error(`Network response was not ok: ${a.status} ${l}`);
|
|
101
79
|
}
|
|
102
80
|
if (!t) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
(E = (u = (l = (s = i.result) == null ? void 0 : s.output) == null ? void 0 : l.messages) == null ? void 0 : u[0]) != null && E.content && (yield {
|
|
107
|
-
text: i.result.output.messages[0].content,
|
|
81
|
+
const l = await a.json();
|
|
82
|
+
l.response && (yield {
|
|
83
|
+
text: l.response,
|
|
108
84
|
done: !0
|
|
109
85
|
});
|
|
110
86
|
return;
|
|
111
87
|
}
|
|
112
|
-
const
|
|
113
|
-
if (!
|
|
114
|
-
const
|
|
115
|
-
let
|
|
88
|
+
const w = (s = a.body) == null ? void 0 : s.getReader();
|
|
89
|
+
if (!w) throw new Error("No reader available");
|
|
90
|
+
const I = new TextDecoder();
|
|
91
|
+
let i = "", y = !1;
|
|
116
92
|
try {
|
|
117
93
|
for (; ; ) {
|
|
118
|
-
const { done:
|
|
119
|
-
if (
|
|
94
|
+
const { done: l, value: A } = await w.read();
|
|
95
|
+
if (l)
|
|
120
96
|
break;
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
let
|
|
124
|
-
for (; (
|
|
125
|
-
`,
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
const
|
|
129
|
-
if (!
|
|
97
|
+
const E = I.decode(A, { stream: !0 });
|
|
98
|
+
i += E;
|
|
99
|
+
let u = 0, g;
|
|
100
|
+
for (; (g = i.indexOf(`
|
|
101
|
+
`, u)) !== -1; ) {
|
|
102
|
+
const d = i.slice(u, g).trim();
|
|
103
|
+
if (u = g + 1, d && d.startsWith("data: ")) {
|
|
104
|
+
const h = d.slice(6).trim();
|
|
105
|
+
if (!h || h === "[DONE]") {
|
|
130
106
|
yield { text: "", done: !0 };
|
|
131
107
|
return;
|
|
132
108
|
}
|
|
133
109
|
try {
|
|
134
|
-
const
|
|
135
|
-
if (
|
|
136
|
-
throw new Error(`
|
|
137
|
-
if ((
|
|
138
|
-
|
|
139
|
-
else if (((x = n.result) == null ? void 0 : x.type) === "complete") {
|
|
140
|
-
const A = ((S = (T = (C = n.result.output) == null ? void 0 : C.messages) == null ? void 0 : T[0]) == null ? void 0 : S.content) ?? "";
|
|
141
|
-
!d && A ? yield { text: A, done: !0 } : yield { text: "", done: !0 };
|
|
110
|
+
const o = JSON.parse(h);
|
|
111
|
+
if (o.error)
|
|
112
|
+
throw new Error(`Server Error: ${o.error.message}`);
|
|
113
|
+
if (o.response && (y = !0, yield { text: o.response, done: o.done || !1 }), o.done) {
|
|
114
|
+
yield { text: "", done: !0 };
|
|
142
115
|
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return;
|
|
147
|
-
} else
|
|
148
|
-
d = !0, yield { text: n.response, done: !1 };
|
|
149
|
-
} catch (n) {
|
|
150
|
-
console.warn("Error parsing JSON chunk:", n);
|
|
116
|
+
}
|
|
117
|
+
} catch (o) {
|
|
118
|
+
console.warn("Error parsing JSON chunk:", o, "Chunk:", h);
|
|
151
119
|
}
|
|
152
|
-
}
|
|
120
|
+
} else d && (y = !0, yield { text: d, done: !1 });
|
|
153
121
|
}
|
|
154
|
-
|
|
122
|
+
i = i.slice(u), i.length > 1e6 && (console.warn("Buffer too large, truncating..."), i = i.slice(-5e5));
|
|
155
123
|
}
|
|
156
|
-
|
|
124
|
+
y && (yield { text: "", done: !0 });
|
|
157
125
|
} finally {
|
|
158
|
-
|
|
126
|
+
w.releaseLock();
|
|
159
127
|
}
|
|
160
|
-
} catch (
|
|
161
|
-
throw
|
|
128
|
+
} catch (n) {
|
|
129
|
+
throw n.name === "AbortError" ? new Error("Connection timed out. Please check if the server is running.") : n.name === "TypeError" && n.message.includes("Failed to fetch") ? new Error("Could not connect to the server. Please check if the server is running.") : n;
|
|
162
130
|
}
|
|
163
131
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
132
|
+
async clearConversationHistory(e) {
|
|
133
|
+
const t = e || this.sessionId;
|
|
134
|
+
if (!t)
|
|
135
|
+
throw new Error("No session ID provided and no current session available");
|
|
136
|
+
if (!this.apiKey)
|
|
137
|
+
throw new Error("API key is required for clearing conversation history");
|
|
138
|
+
const s = {
|
|
139
|
+
"Content-Type": "application/json",
|
|
140
|
+
"X-Session-ID": t,
|
|
141
|
+
"X-API-Key": this.apiKey
|
|
142
|
+
};
|
|
143
|
+
try {
|
|
144
|
+
const n = await fetch(`${this.apiUrl}/admin/chat-history/${t}`, {
|
|
145
|
+
...this.getFetchOptions({
|
|
146
|
+
method: "DELETE",
|
|
147
|
+
headers: s
|
|
148
|
+
})
|
|
149
|
+
});
|
|
150
|
+
if (!n.ok) {
|
|
151
|
+
const a = await n.text();
|
|
152
|
+
throw new Error(`Failed to clear conversation history: ${n.status} ${a}`);
|
|
153
|
+
}
|
|
154
|
+
return await n.json();
|
|
155
|
+
} catch (n) {
|
|
156
|
+
throw n.name === "TypeError" && n.message.includes("Failed to fetch") ? new Error("Could not connect to the server. Please check if the server is running.") : n;
|
|
176
157
|
}
|
|
177
|
-
const s = await t.json();
|
|
178
|
-
if (s.error)
|
|
179
|
-
throw new Error(`MCP Error: ${s.error.message}`);
|
|
180
|
-
return s;
|
|
181
158
|
}
|
|
182
159
|
}
|
|
183
|
-
let
|
|
184
|
-
const
|
|
185
|
-
|
|
160
|
+
let v = null;
|
|
161
|
+
const S = (r, e = null, t = null) => {
|
|
162
|
+
v = new x({ apiUrl: r, apiKey: e, sessionId: t });
|
|
186
163
|
};
|
|
187
|
-
async function*
|
|
188
|
-
if (!
|
|
189
|
-
throw new Error("API not configured. Please call configureApi() with your server URL before using any API functions.");
|
|
190
|
-
yield* f.streamChat(r, e);
|
|
191
|
-
}
|
|
192
|
-
async function F(r) {
|
|
193
|
-
if (!f)
|
|
164
|
+
async function* P(r, e = !0) {
|
|
165
|
+
if (!v)
|
|
194
166
|
throw new Error("API not configured. Please call configureApi() with your server URL before using any API functions.");
|
|
195
|
-
|
|
167
|
+
yield* v.streamChat(r, e);
|
|
196
168
|
}
|
|
197
169
|
export {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
N as streamChat
|
|
170
|
+
x as ApiClient,
|
|
171
|
+
S as configureApi,
|
|
172
|
+
P as streamChat
|
|
202
173
|
};
|
|
203
174
|
//# sourceMappingURL=api.mjs.map
|
package/dist/api.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.mjs","sources":["../api.ts"],"sourcesContent":["// For Node.js environments, we can use http.Agent for connection pooling\nlet httpAgent: any = null;\nlet httpsAgent: any = null;\n\n// Initialize agents for connection pooling in Node.js environments\nif (typeof window === 'undefined') {\n // Lazy load to avoid including 'http' in browser bundles\n Promise.all([\n import('http').catch(() => null),\n import('https').catch(() => null)\n ]).then(([http, https]) => {\n if (http?.default?.Agent) {\n httpAgent = new http.default.Agent({ keepAlive: true });\n } else if (http?.Agent) {\n httpAgent = new http.Agent({ keepAlive: true });\n }\n \n if (https?.default?.Agent) {\n httpsAgent = new https.default.Agent({ keepAlive: true });\n } else if (https?.Agent) {\n httpsAgent = new https.Agent({ keepAlive: true });\n }\n }).catch(err => {\n // Silently fail - connection pooling is optional\n console.warn('Failed to initialize HTTP agents:', err.message);\n });\n}\n\n// Define the StreamResponse interface\nexport interface StreamResponse {\n text: string;\n done: boolean;\n}\n\nexport interface ChatResponse {\n response: string;\n}\n\n// MCP Protocol interfaces\ninterface MCPRequest {\n jsonrpc: \"2.0\";\n method: string;\n params: {\n name: string;\n arguments: {\n messages?: Array<{\n role: string;\n content: string;\n }>;\n stream?: boolean;\n tools?: Array<{\n name: string;\n parameters: Record<string, any>;\n }>;\n };\n };\n id: string;\n}\n\ninterface MCPResponse {\n jsonrpc: \"2.0\";\n id: string;\n result?: {\n type?: \"start\" | \"chunk\" | \"complete\";\n chunk?: {\n content: string;\n };\n output?: {\n messages: Array<{\n role: string;\n content: string;\n }>;\n };\n };\n error?: {\n code: number;\n message: string;\n };\n}\n\nexport class ApiClient {\n private readonly apiUrl: string;\n private readonly apiKey: string | null;\n private sessionId: string | null; // Session ID can be mutable\n\n constructor(config: { apiUrl: string; apiKey?: string | null; sessionId?: string | null }) {\n if (!config.apiUrl || typeof config.apiUrl !== 'string') {\n throw new Error('API URL must be a valid string');\n }\n if (config.apiKey !== undefined && config.apiKey !== null && typeof config.apiKey !== 'string') {\n throw new Error('API key must be a valid string or null');\n }\n if (config.sessionId !== undefined && config.sessionId !== null && typeof config.sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n \n this.apiUrl = config.apiUrl;\n this.apiKey = config.apiKey ?? null;\n this.sessionId = config.sessionId ?? null;\n }\n\n public setSessionId(sessionId: string | null): void {\n if (sessionId !== null && typeof sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n this.sessionId = sessionId;\n }\n\n public getSessionId(): string | null {\n return this.sessionId;\n }\n\n // Helper to get fetch options with connection pooling if available\n private getFetchOptions(options: RequestInit = {}): RequestInit {\n const baseOptions: RequestInit = {};\n \n // Environment-specific options\n if (typeof window === 'undefined') {\n // Node.js: Use connection pooling agent\n const isHttps = this.apiUrl.startsWith('https:');\n const agent = isHttps ? httpsAgent : httpAgent;\n if (agent) {\n (baseOptions as any).agent = agent;\n }\n } else {\n // Browser: Use keep-alive header\n baseOptions.headers = { 'Connection': 'keep-alive' };\n }\n\n // Common headers\n const headers: Record<string, string> = {\n 'X-Request-ID': Date.now().toString(36) + Math.random().toString(36).substring(2),\n };\n\n // Merge base options headers (for browser keep-alive)\n if (baseOptions.headers) {\n Object.assign(headers, baseOptions.headers);\n }\n\n // Merge original request headers\n if (options.headers) {\n Object.assign(headers, options.headers);\n }\n\n if (this.apiKey) {\n headers['X-API-Key'] = this.apiKey;\n }\n\n if (this.sessionId) {\n headers['X-Session-ID'] = this.sessionId;\n }\n\n return {\n ...options,\n ...baseOptions,\n headers,\n };\n }\n\n // Create MCP request\n private createMCPRequest(message: string, stream: boolean = true): MCPRequest {\n return {\n jsonrpc: \"2.0\",\n method: \"tools/call\",\n params: {\n name: \"chat\",\n arguments: {\n messages: [\n { role: \"user\", content: message }\n ],\n stream\n }\n },\n id: Date.now().toString(36) + Math.random().toString(36).substring(2)\n };\n }\n\n // Create MCP tools request\n private createMCPToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): MCPRequest {\n return {\n jsonrpc: \"2.0\",\n method: \"tools/call\",\n params: {\n name: \"tools\",\n arguments: {\n tools\n }\n },\n id: Date.now().toString(36) + Math.random().toString(36).substring(2)\n };\n }\n\n public async *streamChat(\n message: string,\n stream: boolean = true\n ): AsyncGenerator<StreamResponse> {\n try {\n // Add timeout to the fetch request\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 60000); // 60 second timeout\n\n const response = await fetch(`${this.apiUrl}/v1/chat`, {\n ...this.getFetchOptions({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': stream ? 'text/event-stream' : 'application/json'\n },\n body: JSON.stringify(this.createMCPRequest(message, stream)),\n }),\n signal: controller.signal\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Network response was not ok: ${response.status} ${errorText}`);\n }\n\n if (!stream) {\n // Handle non-streaming response\n const data = await response.json() as MCPResponse;\n if (data.error) {\n throw new Error(`MCP Error: ${data.error.message}`);\n }\n if (data.result?.output?.messages?.[0]?.content) {\n yield {\n text: data.result.output.messages[0].content,\n done: true\n };\n }\n return;\n }\n \n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader available');\n\n const decoder = new TextDecoder();\n let buffer = '';\n let hasReceivedContent = false;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n const chunk = decoder.decode(value, { stream: true });\n buffer += chunk;\n \n // Process complete lines immediately as they arrive\n let lineStartIndex = 0;\n let newlineIndex;\n \n while ((newlineIndex = buffer.indexOf('\\n', lineStartIndex)) !== -1) {\n const line = buffer.slice(lineStartIndex, newlineIndex).trim();\n lineStartIndex = newlineIndex + 1;\n \n if (line && line.startsWith('data: ')) {\n const jsonText = line.slice(6).trim();\n \n // Check for [DONE] message or empty data lines\n if (!jsonText || jsonText === '[DONE]') {\n yield { text: '', done: true };\n return;\n }\n\n try {\n const data = JSON.parse(jsonText) as MCPResponse;\n \n if (data.error) {\n throw new Error(`MCP Error: ${data.error.message}`);\n }\n \n // Handle MCP protocol format - server sends chunks of new text directly\n if (data.result?.type === 'chunk' && data.result.chunk?.content) {\n hasReceivedContent = true;\n yield { text: data.result.chunk.content, done: false };\n } else if (data.result?.type === 'complete') {\n // Final piece of content or just the done signal\n const finalText = data.result.output?.messages?.[0]?.content ?? '';\n // Only yield final text if we haven't received incremental chunks\n if (!hasReceivedContent && finalText) {\n yield { text: finalText, done: true };\n } else {\n yield { text: '', done: true };\n }\n return;\n } else if ('response' in data && typeof data.response === 'string') {\n // Handle direct server response format (legacy compatibility)\n const isDone = 'done' in data && data.done === true;\n \n if (isDone) {\n // For final response, only yield if we haven't received incremental chunks\n if (!hasReceivedContent && data.response) {\n yield { text: data.response, done: true };\n } else {\n yield { text: '', done: true };\n }\n return;\n } else {\n // For incremental chunks, always yield\n hasReceivedContent = true;\n yield { text: data.response, done: false };\n }\n }\n \n } catch (parseError) {\n console.warn('Error parsing JSON chunk:', parseError);\n }\n }\n }\n \n // Keep remaining incomplete line in buffer\n buffer = buffer.slice(lineStartIndex);\n \n // Prevent buffer from growing too large\n if (buffer.length > 1000000) { // 1MB limit\n console.warn('Buffer too large, truncating...');\n buffer = buffer.slice(-500000); // Keep last 500KB\n }\n }\n \n // If we exit the while loop naturally, ensure we send a done signal\n if (hasReceivedContent) {\n yield { text: '', done: true };\n }\n \n } finally {\n reader.releaseLock();\n }\n \n } catch (error: any) {\n if (error.name === 'AbortError') {\n throw new Error('Connection timed out. Please check if the server is running.');\n } else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n throw new Error('Could not connect to the server. Please check if the server is running.');\n } else {\n // Re-throw the error to be caught by the caller\n throw error;\n }\n }\n }\n\n // New function to send tools request\n public async sendToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): Promise<MCPResponse> {\n const response = await fetch(`${this.apiUrl}/v1/chat`, this.getFetchOptions({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(this.createMCPToolsRequest(tools)),\n }));\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Network response was not ok: ${response.status} ${errorText}`);\n }\n\n const data = await response.json() as MCPResponse;\n if (data.error) {\n throw new Error(`MCP Error: ${data.error.message}`);\n }\n\n return data;\n }\n}\n\n// Legacy compatibility functions - these create a default client instance\n// These are kept for backward compatibility but should be deprecated in favor of the class-based approach\n\nlet defaultClient: ApiClient | null = null;\n\n// Configure the API with a custom URL, API key (optional), and session ID (optional)\nexport const configureApi = (apiUrl: string, apiKey: string | null = null, sessionId: string | null = null): void => {\n defaultClient = new ApiClient({ apiUrl, apiKey, sessionId });\n}\n\n// Legacy streamChat function that uses the default client\nexport async function* streamChat(\n message: string,\n stream: boolean = true\n): AsyncGenerator<StreamResponse> {\n if (!defaultClient) {\n throw new Error('API not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n \n yield* defaultClient.streamChat(message, stream);\n}\n\n// Legacy sendToolsRequest function that uses the default client\nexport async function sendToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): Promise<MCPResponse> {\n if (!defaultClient) {\n throw new Error('API not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n \n return defaultClient.sendToolsRequest(tools);\n}"],"names":["httpAgent","httpsAgent","http","https","_a","_b","err","ApiClient","config","__publicField","sessionId","options","baseOptions","agent","headers","message","stream","tools","_c","_d","_e","_f","_g","_h","_i","_j","_k","controller","timeoutId","response","errorText","data","reader","decoder","buffer","hasReceivedContent","done","value","chunk","lineStartIndex","newlineIndex","line","jsonText","finalText","parseError","error","defaultClient","configureApi","apiUrl","apiKey","streamChat","sendToolsRequest"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.mjs","sources":["../api.ts"],"sourcesContent":["// For Node.js environments, we can use http.Agent for connection pooling\nlet httpAgent: any = null;\nlet httpsAgent: any = null;\n\n// Initialize agents for connection pooling in Node.js environments\nif (typeof window === 'undefined') {\n // Lazy load to avoid including 'http' in browser bundles\n Promise.all([\n import('http').catch(() => null),\n import('https').catch(() => null)\n ]).then(([http, https]) => {\n if (http?.default?.Agent) {\n httpAgent = new http.default.Agent({ keepAlive: true });\n } else if (http?.Agent) {\n httpAgent = new http.Agent({ keepAlive: true });\n }\n \n if (https?.default?.Agent) {\n httpsAgent = new https.default.Agent({ keepAlive: true });\n } else if (https?.Agent) {\n httpsAgent = new https.Agent({ keepAlive: true });\n }\n }).catch(err => {\n // Silently fail - connection pooling is optional\n console.warn('Failed to initialize HTTP agents:', err.message);\n });\n}\n\n// Define the StreamResponse interface\nexport interface StreamResponse {\n text: string;\n done: boolean;\n}\n\n// The server now returns this directly for non-streaming chat\nexport interface ChatResponse {\n response: string;\n sources?: any[];\n}\n\n// The request body for the /v1/chat endpoint\ninterface ChatRequest {\n messages: Array<{ role: string; content: string; }>;\n stream: boolean;\n}\n\nexport class ApiClient {\n private readonly apiUrl: string;\n private readonly apiKey: string | null;\n private sessionId: string | null; // Session ID can be mutable\n\n constructor(config: { apiUrl: string; apiKey?: string | null; sessionId?: string | null }) {\n if (!config.apiUrl || typeof config.apiUrl !== 'string') {\n throw new Error('API URL must be a valid string');\n }\n if (config.apiKey !== undefined && config.apiKey !== null && typeof config.apiKey !== 'string') {\n throw new Error('API key must be a valid string or null');\n }\n if (config.sessionId !== undefined && config.sessionId !== null && typeof config.sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n \n this.apiUrl = config.apiUrl;\n this.apiKey = config.apiKey ?? null;\n this.sessionId = config.sessionId ?? null;\n }\n\n public setSessionId(sessionId: string | null): void {\n if (sessionId !== null && typeof sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n this.sessionId = sessionId;\n }\n\n public getSessionId(): string | null {\n return this.sessionId;\n }\n\n // Helper to get fetch options with connection pooling if available\n private getFetchOptions(options: RequestInit = {}): RequestInit {\n const baseOptions: RequestInit = {};\n \n // Environment-specific options\n if (typeof window === 'undefined') {\n // Node.js: Use connection pooling agent\n const isHttps = this.apiUrl.startsWith('https:');\n const agent = isHttps ? httpsAgent : httpAgent;\n if (agent) {\n (baseOptions as any).agent = agent;\n }\n } else {\n // Browser: Use keep-alive header\n baseOptions.headers = { 'Connection': 'keep-alive' };\n }\n\n // Common headers\n const headers: Record<string, string> = {\n 'X-Request-ID': Date.now().toString(36) + Math.random().toString(36).substring(2),\n };\n\n // Merge base options headers (for browser keep-alive)\n if (baseOptions.headers) {\n Object.assign(headers, baseOptions.headers);\n }\n\n // Merge original request headers\n if (options.headers) {\n Object.assign(headers, options.headers);\n }\n\n if (this.apiKey) {\n headers['X-API-Key'] = this.apiKey;\n }\n\n if (this.sessionId) {\n headers['X-Session-ID'] = this.sessionId;\n }\n\n return {\n ...options,\n ...baseOptions,\n headers,\n };\n }\n\n // Create Chat request\n private createChatRequest(message: string, stream: boolean = true): ChatRequest {\n return {\n messages: [\n { role: \"user\", content: message }\n ],\n stream\n };\n }\n\n public async *streamChat(\n message: string,\n stream: boolean = true\n ): AsyncGenerator<StreamResponse> {\n try {\n // Add timeout to the fetch request\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 60000); // 60 second timeout\n\n const response = await fetch(`${this.apiUrl}/v1/chat`, {\n ...this.getFetchOptions({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': stream ? 'text/event-stream' : 'application/json'\n },\n body: JSON.stringify(this.createChatRequest(message, stream)),\n }),\n signal: controller.signal\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Network response was not ok: ${response.status} ${errorText}`);\n }\n\n if (!stream) {\n // Handle non-streaming response\n const data = await response.json() as ChatResponse;\n if (data.response) {\n yield {\n text: data.response,\n done: true\n };\n }\n return;\n }\n \n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader available');\n\n const decoder = new TextDecoder();\n let buffer = '';\n let hasReceivedContent = false;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n const chunk = decoder.decode(value, { stream: true });\n buffer += chunk;\n \n // Process complete lines immediately as they arrive\n let lineStartIndex = 0;\n let newlineIndex;\n \n while ((newlineIndex = buffer.indexOf('\\n', lineStartIndex)) !== -1) {\n const line = buffer.slice(lineStartIndex, newlineIndex).trim();\n lineStartIndex = newlineIndex + 1;\n \n if (line && line.startsWith('data: ')) {\n const jsonText = line.slice(6).trim();\n \n if (!jsonText || jsonText === '[DONE]') {\n yield { text: '', done: true };\n return;\n }\n\n try {\n const data = JSON.parse(jsonText);\n \n if (data.error) {\n throw new Error(`Server Error: ${data.error.message}`);\n }\n \n if (data.response) {\n hasReceivedContent = true;\n yield { text: data.response, done: data.done || false };\n }\n\n if (data.done) {\n yield { text: '', done: true };\n return;\n }\n \n } catch (parseError) {\n console.warn('Error parsing JSON chunk:', parseError, 'Chunk:', jsonText);\n }\n } else if (line) {\n // Handle raw text chunks that are not in SSE format\n hasReceivedContent = true;\n yield { text: line, done: false };\n }\n }\n \n buffer = buffer.slice(lineStartIndex);\n \n if (buffer.length > 1000000) { // 1MB limit\n console.warn('Buffer too large, truncating...');\n buffer = buffer.slice(-500000); // Keep last 500KB\n }\n }\n \n if (hasReceivedContent) {\n yield { text: '', done: true };\n }\n \n } finally {\n reader.releaseLock();\n }\n \n } catch (error: any) {\n if (error.name === 'AbortError') {\n throw new Error('Connection timed out. Please check if the server is running.');\n } else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n throw new Error('Could not connect to the server. Please check if the server is running.');\n } else {\n throw error;\n }\n }\n }\n\n public async clearConversationHistory(sessionId?: string): Promise<{\n status: string;\n message: string;\n session_id: string;\n deleted_count: number;\n timestamp: string;\n }> {\n /**\n * Clear conversation history for a session.\n * \n * @param sessionId - Optional session ID to clear. If not provided, uses current session.\n * @returns Promise resolving to operation result\n * @throws Error if the operation fails\n */\n const targetSessionId = sessionId || this.sessionId;\n \n if (!targetSessionId) {\n throw new Error('No session ID provided and no current session available');\n }\n \n if (!this.apiKey) {\n throw new Error('API key is required for clearing conversation history');\n }\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Session-ID': targetSessionId,\n 'X-API-Key': this.apiKey\n };\n \n try {\n const response = await fetch(`${this.apiUrl}/admin/chat-history/${targetSessionId}`, {\n ...this.getFetchOptions({\n method: 'DELETE',\n headers\n })\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to clear conversation history: ${response.status} ${errorText}`);\n }\n \n const result = await response.json();\n return result;\n \n } catch (error: any) {\n if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n throw new Error('Could not connect to the server. Please check if the server is running.');\n } else {\n throw error;\n }\n }\n }\n}\n\n// Legacy compatibility functions - these create a default client instance\n// These are kept for backward compatibility but should be deprecated in favor of the class-based approach\n\nlet defaultClient: ApiClient | null = null;\n\n// Configure the API with a custom URL, API key (optional), and session ID (optional)\nexport const configureApi = (apiUrl: string, apiKey: string | null = null, sessionId: string | null = null): void => {\n defaultClient = new ApiClient({ apiUrl, apiKey, sessionId });\n}\n\n// Legacy streamChat function that uses the default client\nexport async function* streamChat(\n message: string,\n stream: boolean = true\n): AsyncGenerator<StreamResponse> {\n if (!defaultClient) {\n throw new Error('API not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n \n yield* defaultClient.streamChat(message, stream);\n}\n\n"],"names":["httpAgent","httpsAgent","http","https","_a","_b","err","ApiClient","config","__publicField","sessionId","options","baseOptions","agent","headers","message","stream","controller","timeoutId","response","errorText","data","reader","decoder","buffer","hasReceivedContent","done","value","chunk","lineStartIndex","newlineIndex","line","jsonText","parseError","error","targetSessionId","defaultClient","configureApi","apiUrl","apiKey","streamChat"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schmitech/chatbot-api",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.3",
|
|
5
5
|
"description": "API client for the ORBIT MCP server",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/api.cjs",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"preview": "vite preview",
|
|
30
30
|
"test": "vitest",
|
|
31
31
|
"test:watch": "vitest",
|
|
32
|
+
"test:npm": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' ./test/test-npm-package.ts",
|
|
32
33
|
"test-query": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' ./test/run-query.js",
|
|
33
34
|
"test-query-from-pairs": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' ./test/run-query-from-pairs.js"
|
|
34
35
|
},
|