@schmitech/chatbot-api 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,140 +1,74 @@
1
- # 🤖 Chatbot API Client
1
+ # 🤖 ORBIT Chatbot API Client
2
2
 
3
- A JavaScript/TypeScript client for seamless interaction with the Chatbot server, now supporting API key authentication and session tracking.
4
-
5
- ---
3
+ A TypeScript/JavaScript client for seamless interaction with the ORBIT server, supporting secure API key authentication, temporary key exchange, and session tracking.
6
4
 
7
5
  ## 📥 Installation
8
6
 
9
- ### 📍 Local Development (npm link)
10
-
11
- Use during local development:
12
-
13
7
  ```bash
14
- npm run build
15
- npm link
16
-
17
- # In your project directory
18
- npm link @schmitech/chatbot-api
8
+ npm install @schmitech/chatbot-api
19
9
  ```
20
10
 
21
- ### 📂 Local Directory Install
11
+ ## ⚙️ Basic Usage
22
12
 
23
- Direct local installation:
13
+ ### Configuration
24
14
 
25
- ```bash
26
- npm run build
27
- npm install /path/to/qa-chatbot-server/api
28
- ```
29
-
30
- ### 🌐 CDN Integration
15
+ First, configure the API client with your server details:
31
16
 
32
- Integrate directly into websites via CDN:
17
+ ```typescript
18
+ import { configureApi, streamChat, initializeChatbot } from '@schmitech/chatbot-api';
33
19
 
34
- ```html
35
- <script type="module">
36
- import { configureApi, streamChat } from 'https://cdn.jsdelivr.net/npm/@schmitech/chatbot-api/dist/api.mjs';
20
+ // Basic configuration
21
+ configureApi('https://your-api-server.com', 'your-api-key');
37
22
 
38
- configureApi({
39
- apiUrl: 'https://your-api-server.com',
40
- apiKey: 'your-api-key',
41
- sessionId: 'your-session-id' // Optional
42
- });
43
-
44
- async function handleChat() {
45
- for await (const response of streamChat('Hello', false)) {
46
- console.log(response.text);
47
- }
48
- }
49
- </script>
23
+ // For enhanced security with temporary key exchange
24
+ await initializeChatbot('your-api-key', 'https://your-origin.com');
50
25
  ```
51
26
 
52
- ---
53
-
54
- ## ⚙️ Usage
55
-
56
- ### 🚨 Configuration (Required)
27
+ ### Streaming Chat Example
57
28
 
58
- You must configure the API client before usage:
59
-
60
- ```javascript
61
- import { configureApi, streamChat } from '@schmitech/chatbot-api';
62
-
63
- configureApi({
64
- apiUrl: 'https://your-api-server.com',
65
- apiKey: 'your-api-key',
66
- sessionId: 'your-session-id' // Optional
67
- });
68
- ```
69
-
70
- ### 📖 Basic Example
71
-
72
- ```javascript
29
+ ```typescript
73
30
  async function chat() {
74
- configureApi({
75
- apiUrl: 'https://your-api-server.com',
76
- apiKey: 'your-api-key',
77
- sessionId: 'user_123_session_456' // Optional
78
- });
79
-
80
- for await (const response of streamChat('Hello, how can I help?', false)) {
31
+ for await (const response of streamChat('Hello, how can I help?', true)) {
81
32
  console.log(response.text);
82
- if (response.done) console.log('Chat complete!');
83
- }
84
- }
85
-
86
- chat();
87
- ```
88
-
89
- ### 🎙️ Voice-enabled Example
90
-
91
- ```javascript
92
- async function chatWithVoice() {
93
- configureApi({
94
- apiUrl: 'https://your-api-server.com',
95
- apiKey: 'your-api-key',
96
- sessionId: 'user_123_session_456' // Optional
97
- });
98
-
99
- for await (const response of streamChat('Tell me a joke', true)) {
100
- if (response.type === 'audio') {
101
- console.log('Received audio content');
102
- } else {
103
- console.log(response.text);
33
+ if (response.done) {
34
+ console.log('Chat complete!');
104
35
  }
105
- if (response.done) console.log('Chat complete!');
106
36
  }
107
37
  }
108
-
109
- chatWithVoice();
110
38
  ```
111
39
 
112
- ---
113
-
114
40
  ## ⚛️ React Integration
115
41
 
116
- Configure once globally:
42
+ Here's how to use the API in a React component:
117
43
 
118
- ```jsx
119
- import React, { useState } from 'react';
120
- import { configureApi, streamChat } from '@schmitech/chatbot-api';
121
-
122
- configureApi({
123
- apiUrl: 'https://your-api-server.com',
124
- apiKey: 'your-api-key',
125
- sessionId: 'user_123_session_456' // Optional
126
- });
44
+ ```tsx
45
+ import React, { useState, useEffect } from 'react';
46
+ import { configureApi, streamChat, initializeChatbot } from '@schmitech/chatbot-api';
127
47
 
128
48
  function ChatComponent() {
129
- const [messages, setMessages] = useState([]);
49
+ const [messages, setMessages] = useState<Array<{ text: string; isUser: boolean }>>([]);
130
50
  const [input, setInput] = useState('');
131
51
 
132
- const handleSubmit = async (e) => {
52
+ useEffect(() => {
53
+ // Configure API and initialize secure key exchange
54
+ const setupApi = async () => {
55
+ try {
56
+ configureApi('https://your-api-server.com', 'your-api-key');
57
+ await initializeChatbot('your-api-key', window.location.origin);
58
+ } catch (error) {
59
+ console.error('Failed to initialize secure API:', error);
60
+ }
61
+ };
62
+
63
+ setupApi();
64
+ }, []);
65
+
66
+ const handleSubmit = async (e: React.FormEvent) => {
133
67
  e.preventDefault();
134
68
  setMessages(prev => [...prev, { text: input, isUser: true }]);
135
69
 
136
70
  let responseText = '';
137
- for await (const response of streamChat(input, false)) {
71
+ for await (const response of streamChat(input, true)) {
138
72
  responseText += response.text;
139
73
  setMessages(prev => [...prev, { text: responseText, isUser: false }]);
140
74
  if (response.done) break;
@@ -144,91 +78,123 @@ function ChatComponent() {
144
78
 
145
79
  return (
146
80
  <form onSubmit={handleSubmit}>
147
- <input value={input} onChange={(e) => setInput(e.target.value)} />
81
+ <input
82
+ value={input}
83
+ onChange={(e) => setInput(e.target.value)}
84
+ placeholder="Type your message..."
85
+ />
148
86
  <button type="submit">Send</button>
149
87
  </form>
150
88
  );
151
89
  }
152
-
153
- export default ChatComponent;
154
90
  ```
155
91
 
156
- ---
157
-
158
92
  ## 📱 Mobile Usage
159
93
 
160
- ### 📲 React Native
94
+ ### React Native Example
161
95
 
162
- ```javascript
163
- configureApi({
164
- apiUrl: 'https://your-api-server.com',
165
- apiKey: 'your-api-key',
166
- sessionId: 'user_123_session_456' // Optional
167
- });
96
+ ```typescript
97
+ import { configureApi, streamChat, initializeChatbot } from '@schmitech/chatbot-api';
168
98
 
169
- async function handleChat(message) {
170
- for await (const response of streamChat(message, false)) {
171
- // Handle response
99
+ // Configure API and initialize secure key exchange
100
+ const setupApi = async () => {
101
+ try {
102
+ configureApi('https://your-api-server.com', 'your-api-key');
103
+ await initializeChatbot('your-api-key', 'react-native-client');
104
+ } catch (error) {
105
+ console.error('Failed to initialize secure API:', error);
106
+ }
107
+ };
108
+
109
+ async function handleChat(message: string) {
110
+ for await (const response of streamChat(message, true)) {
111
+ // Handle streaming response
112
+ console.log(response.text);
113
+ if (response.done) {
114
+ console.log('Chat complete!');
115
+ }
172
116
  }
173
117
  }
174
118
  ```
175
119
 
176
- ---
177
-
178
- ## 📚 API Reference
120
+ ## 🌐 CDN Integration
179
121
 
180
- ### `configureApi(config)`
122
+ You can also use the API directly in the browser via CDN:
181
123
 
182
- | Parameter | Description | Required |
183
- |-----------|-------------|----------|
184
- | `apiUrl` | Chatbot API URL | Yes |
185
- | `apiKey` | API key for authentication | ✅ Yes |
186
- | `sessionId` | Session ID for tracking conversations | ❌ No |
187
-
188
- ---
189
-
190
- ## 📤 Publish to npm
191
-
192
- **Build package:**
124
+ ```html
125
+ <script type="module">
126
+ import { configureApi, streamChat, initializeChatbot } from 'https://cdn.jsdelivr.net/npm/@schmitech/chatbot-api/dist/api.mjs';
127
+
128
+ // Configure API and initialize secure key exchange
129
+ const setupApi = async () => {
130
+ try {
131
+ configureApi('https://your-api-server.com', 'your-api-key');
132
+ await initializeChatbot('your-api-key', window.location.origin);
133
+ } catch (error) {
134
+ console.error('Failed to initialize secure API:', error);
135
+ }
136
+ };
193
137
 
194
- ```bash
195
- npm run build
138
+ async function handleChat() {
139
+ for await (const response of streamChat('Hello', true)) {
140
+ console.log(response.text);
141
+ }
142
+ }
143
+ </script>
196
144
  ```
197
145
 
198
- **Test locally (optional):**
146
+ ## 📚 API Reference
199
147
 
200
- ```bash
201
- npm pack --dry-run
202
- ```
148
+ ### `configureApi(apiUrl: string, apiKey?: string, sessionId?: string)`
203
149
 
204
- **Update version:**
150
+ Configure the API client with server details.
205
151
 
206
- ```bash
207
- npm version [patch|minor|major]
208
- ```
152
+ | Parameter | Type | Required | Description |
153
+ |-----------|------|----------|-------------|
154
+ | `apiUrl` | string | Yes | Chatbot API server URL |
155
+ | `apiKey` | string | No | API key for authentication |
156
+ | `sessionId` | string | No | Session ID for conversation tracking |
209
157
 
210
- **Publish:**
158
+ ### `initializeChatbot(apiKey: string, origin: string)`
211
159
 
212
- ```bash
213
- npm publish --access public
214
- ```
160
+ Initialize secure key exchange for enhanced security.
215
161
 
216
- ---
162
+ | Parameter | Type | Required | Description |
163
+ |-----------|------|----------|-------------|
164
+ | `apiKey` | string | Yes | Your permanent API key |
165
+ | `origin` | string | Yes | The origin of your application (e.g., window.location.origin) |
217
166
 
218
- ## 🛠️ Development
167
+ ### `streamChat(message: string, stream: boolean = true)`
219
168
 
220
- ### 🧪 Testing
169
+ Stream chat responses from the server.
221
170
 
222
- ```bash
223
- # Test single query
224
- npm run test-query "your query" "http://your-api-server.com" "your-api-key" ["your-session-id"]
171
+ | Parameter | Type | Default | Description |
172
+ |-----------|------|---------|-------------|
173
+ | `message` | string | - | The message to send to the chat |
174
+ | `stream` | boolean | true | Whether to stream the response |
175
+
176
+ Returns an AsyncGenerator that yields `StreamResponse` objects:
225
177
 
226
- # Test multiple queries from JSON file
227
- npm run test-query-from-pairs questions.json "http://your-api-server.com" "your-api-key" [number_of_questions] ["your-session-id"]
178
+ ```typescript
179
+ interface StreamResponse {
180
+ text: string; // The text content of the response
181
+ done: boolean; // Whether this is the final response
182
+ }
228
183
  ```
229
184
 
230
- ---
185
+ ## 🔒 Security Features
186
+
187
+ - **Temporary Key Exchange**: Permanent API keys are exchanged for temporary session keys
188
+ - **Origin Validation**: Server validates the origin of requests for enhanced security
189
+ - **Automatic Key Refresh**: Temporary keys are automatically refreshed before expiration
190
+ - **Request Signing**: Requests are signed for additional security
191
+ - **Rate Limiting**: Built-in rate limiting to prevent abuse
192
+ - **Session Tracking**: Secure session management for conversation continuity
231
193
 
232
- ## 📃 License
194
+ ### Security Best Practices
233
195
 
234
- MIT License - See [LICENSE](LICENSE).
196
+ - Always use HTTPS for your API URL
197
+ - Keep your API key secure and never expose it in client-side code
198
+ - Use environment variables for sensitive configuration
199
+ - Implement proper error handling for authentication failures
200
+ - Monitor for security events using the `chatbot:auth:failed` event
package/api.d.ts CHANGED
@@ -26,6 +26,7 @@ interface MCPResponse {
26
26
  };
27
27
  }
28
28
  export declare const configureApi: (apiUrl: string, apiKey?: string | null, sessionId?: string | null) => void;
29
+ export declare const initializeChatbot: (permanentApiKey: string, customOrigin?: string) => Promise<void>;
29
30
  export declare function streamChat(message: string, stream?: boolean): AsyncGenerator<StreamResponse>;
30
31
  export declare function sendToolsRequest(tools: Array<{
31
32
  name: string;
package/dist/api.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let b=null,N=null,O=null;const $=(t,e=null,r=null)=>{if(!t||typeof t!="string")throw new Error("API URL must be a valid string");if(e!==null&&typeof e!="string")throw new Error("API key must be a valid string or null");if(r!==null&&typeof r!="string")throw new Error("Session ID must be a valid string or null");b=t,N=e,O=r},R=()=>{if(!b)throw new Error("API URL not configured. Please call configureApi() with your server URL before using any API functions.");return b},q=()=>N,L=()=>O,j=(t,e={})=>{t.startsWith("https:");const n={Connection:"keep-alive","X-Request-ID":Date.now().toString(36)+Math.random().toString(36).substring(2)},i=q();i&&(n["X-API-Key"]=i);const u=L();return u&&(n["X-Session-ID"]=u),{...e,headers:{...e.headers,...n}}},x=(t,e=!0)=>({jsonrpc:"2.0",method:"tools/call",params:{name:"chat",arguments:{messages:[{role:"user",content:t}],stream:e}},id:Date.now().toString(36)+Math.random().toString(36).substring(2)}),J=t=>({jsonrpc:"2.0",method:"tools/call",params:{name:"tools",arguments:{tools:t}},id:Date.now().toString(36)+Math.random().toString(36).substring(2)});async function*T(t,e=!0){var r,n,i,u,k,E,S,A,P;try{const a=R(),v=new AbortController,D=setTimeout(()=>v.abort(),6e4),c=await fetch(`${a}/v1/chat`,{...j(a,{method:"POST",headers:{"Content-Type":"application/json",Accept:e?"text/event-stream":"application/json"},body:JSON.stringify(x(t,e))}),signal:v.signal});if(clearTimeout(D),!c.ok){const o=await c.text();throw new Error(`Network response was not ok: ${c.status} ${o}`)}if(!e){const o=await c.json();if(o.error)throw new Error(`MCP Error: ${o.error.message}`);(u=(i=(n=(r=o.result)==null?void 0:r.output)==null?void 0:n.messages)==null?void 0:i[0])!=null&&u.content&&(yield{text:o.result.output.messages[0].content,done:!0});return}const w=(k=c.body)==null?void 0:k.getReader();if(!w)throw new Error("No reader available");const M=new TextDecoder;let l="",y="";try{for(;;){const{done:o,value:d}=await w.read();if(o)break;const f=M.decode(d,{stream:!0});l+=f;const I=l.split(`
2
- `);l=I.pop()||"";for(const h of I)if(h.trim()&&h.startsWith("data: "))try{const p=h.slice(6).trim();if(p==="[DONE]"){yield{text:"",done:!0};break}const s=JSON.parse(p);if(s.result){let g="";if(s.result.type==="start")continue;if(s.result.type==="chunk"&&s.result.chunk?g=s.result.chunk.content:s.result.type==="complete"&&((S=(E=s.result.output)==null?void 0:E.messages)!=null&&S[0])&&(g=s.result.output.messages[0].content),g){const m=C(g,y);m?(y+=m,yield{text:m,done:s.result.type==="complete"}):s.result.type==="complete"&&(yield{text:"",done:!0})}}}catch(p){console.warn("Error parsing JSON chunk:",h,"Error:",p)}}}finally{w.releaseLock()}if(l&&l.startsWith("data: "))try{const o=l.slice(6).trim();if(o!=="[DONE]"){const d=JSON.parse(o);if((P=(A=d.result)==null?void 0:A.chunk)!=null&&P.content){const f=C(d.result.chunk.content,y);f&&(yield{text:f,done:d.result.type==="complete"})}}}catch(o){console.warn("Error parsing final JSON buffer:",l,"Error:",o)}}catch(a){a.name==="AbortError"?yield{text:"Connection timed out. Please check if the server is running.",done:!0}:a.name==="TypeError"&&a.message.includes("Failed to fetch")?yield{text:"Could not connect to the server. Please check if the server is running.",done:!0}:yield{text:`Error: ${a.message}`,done:!0}}}function C(t,e){if(!e)return t;if(e.endsWith(t))return"";if(t.length>e.length){if(t.startsWith(e))return t.slice(e.length);let r=0;const n=Math.min(e.length,t.length);for(;r<n&&e[r]===t[r];)r++;if(r>e.length/2)return t.slice(r)}return t}async function U(t){const e=R(),r=await fetch(`${e}/v1/chat`,j(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(J(t))}));if(!r.ok){const i=await r.text();throw new Error(`Network response was not ok: ${r.status} ${i}`)}const n=await r.json();if(n.error)throw new Error(`MCP Error: ${n.error.message}`);return n}exports.configureApi=$;exports.sendToolsRequest=U;exports.streamChat=T;
1
+ "use strict";var F=Object.defineProperty;var K=(t,e,n)=>e in t?F(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var M=(t,e,n)=>K(t,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let E=null,S=null,q=null,C=null,f=null;const _=(t,e=null,n=null)=>{if(!t||typeof t!="string")throw new Error("API URL must be a valid string");if(e!==null&&typeof e!="string")throw new Error("API key must be a valid string or null");if(n!==null&&typeof n!="string")throw new Error("Session ID must be a valid string or null");E=t,S=e,q=n},w=()=>{if(!E)throw new Error("API URL not configured. Please call configureApi() with your server URL before using any API functions.");return E},z=()=>S,L=()=>q,H=async(t,e)=>{try{const n=w(),r=await fetch(`${n}/api/v1/exchange-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:t,origin:e||(typeof window<"u"?window.location.origin:"node-client")})});if(!r.ok){const i=await r.text();throw new Error(`Failed to exchange API key: ${r.status} ${i}`)}const o=await r.json();C=o.sessionId,S=o.temporaryKey,q=o.sessionId,t="";const c=o.expiresIn*.9*1e3;f&&clearTimeout(f),f=setTimeout(()=>U(),c)}catch(n){throw n}},U=async()=>{if(C)try{const t=w(),e=await fetch(`${t}/api/v1/refresh-key`,{method:"POST",headers:{"Content-Type":"application/json","X-Session-ID":C,Origin:typeof window<"u"?window.location.origin:"node-client"}});if(!e.ok){const o=await e.text();throw new Error(`Failed to refresh key: ${e.status} ${o}`)}const n=await e.json();S=n.temporaryKey,f&&clearTimeout(f);const r=n.expiresIn*.9*1e3;f=setTimeout(()=>U(),r)}catch(t){typeof window<"u"&&window.dispatchEvent(new CustomEvent("chatbot:auth:failed",{detail:t}))}},X=(t,e={})=>{t.startsWith("https:");const n=Date.now().toString(36)+Math.random().toString(36).substring(2),r=Date.now(),o={Connection:"keep-alive","X-Request-ID":n,"X-Timestamp":r.toString()};typeof window<"u"&&(o["X-Origin"]=window.location.origin,o["X-Referrer"]=document.referrer||"direct");const c=z();c&&(o["X-API-Key"]=c,typeof window<"u"&&(o["X-Signature"]=B(n,r,e.body)));const i=L();return i&&(o["X-Session-ID"]=i),{...e,headers:{...e.headers,...o}}},B=(t,e,n)=>{const r=`${t}:${e}:${n?JSON.stringify(n):""}`;return btoa(r).substring(0,16)};class G{constructor(){M(this,"requests",new Map)}canMakeRequest(e,n=20,r=6e4){const o=Date.now(),i=(this.requests.get(e)||[]).filter(g=>o-g<r);return i.length>=n?!1:(i.push(o),this.requests.set(e,i),this.requests.size>1e3&&this.cleanup(r),!0)}cleanup(e){const n=Date.now();for(const[r,o]of this.requests.entries()){const c=o.filter(i=>n-i<e);c.length===0?this.requests.delete(r):this.requests.set(r,c)}}}const Q=new G,V={config:{monitoring:{enabled:!0}},async loadConfig(){try{const t=w(),e=await fetch(`${t}/api/v1/security/config`);if(e.ok){const n=await e.json();n.monitoring&&(this.config.monitoring={...this.config.monitoring,...n.monitoring})}}catch{}},detectDevTools(){if(typeof window>"u")return!1;const t=160;return window.outerHeight-window.innerHeight>t||window.outerWidth-window.innerWidth>t},async init(){typeof window>"u"||await this.loadConfig()}};typeof window<"u"&&V.init().catch(()=>{});const Y=(t,e=!0)=>({jsonrpc:"2.0",method:"tools/call",params:{name:"chat",arguments:{messages:[{role:"user",content:t}],stream:e}},id:Date.now().toString(36)+Math.random().toString(36).substring(2)}),Z=t=>({jsonrpc:"2.0",method:"tools/call",params:{name:"tools",arguments:{tools:t}},id:Date.now().toString(36)+Math.random().toString(36).substring(2)});async function*ee(t,e=!0){var n,r,o,c,i,g,A,$,O;try{const l=L()||"anonymous";if(!Q.canMakeRequest(l,20,6e4)){yield{text:"Rate limit exceeded. Please wait a moment before sending more messages.",done:!0};return}const j=w(),D=new AbortController,J=setTimeout(()=>D.abort(),6e4),h=await fetch(`${j}/v1/chat`,{...X(j,{method:"POST",headers:{"Content-Type":"application/json",Accept:e?"text/event-stream":"application/json"},body:JSON.stringify(Y(t,e))}),signal:D.signal});if(clearTimeout(J),!h.ok){const a=await h.text();throw new Error(`Network response was not ok: ${h.status} ${a}`)}if(!e){const a=await h.json();if(a.error)throw new Error(`MCP Error: ${a.error.message}`);(c=(o=(r=(n=a.result)==null?void 0:n.output)==null?void 0:r.messages)==null?void 0:o[0])!=null&&c.content&&(yield{text:a.result.output.messages[0].content,done:!0});return}const T=(i=h.body)==null?void 0:i.getReader();if(!T)throw new Error("No reader available");const W=new TextDecoder;let u="",b="",y=!1;try{for(;;){const{done:a,value:p}=await T.read();if(a)break;const m=W.decode(p,{stream:!0});u+=m;let k=0,P;for(;(P=u.indexOf(`
2
+ `,k))!==-1;){const R=u.slice(k,P).trim();if(k=P+1,R&&R.startsWith("data: "))try{const x=R.slice(6).trim();if(x==="[DONE]"){yield{text:"",done:!0};return}if(!x)continue;const s=JSON.parse(x);if(s.error)throw new Error(`MCP Error: ${s.error.message}`);let d="",I=!1;if(s.result){if(s.result.type==="start")continue;if(s.result.type==="chunk"&&s.result.chunk)d=s.result.chunk.content;else if(s.result.type==="complete"&&((A=(g=s.result.output)==null?void 0:g.messages)!=null&&A[0]))if(!y)d=s.result.output.messages[0].content,I=!0;else continue}if(!d&&"response"in s&&typeof s.response=="string"&&(d=s.response),"done"in s&&s.done===!0&&(I=!0),d){const v=N(d,b);v&&(b+=v,y=!0,yield{text:v,done:I})}if(I){y||(yield{text:"",done:!0});return}}catch{}}u=u.slice(k),u.length>1e6&&(u=u.slice(-5e5))}y&&(yield{text:"",done:!0})}finally{T.releaseLock()}if(u&&u.startsWith("data: "))try{const a=u.slice(6).trim();if(a&&a!=="[DONE]"){const p=JSON.parse(a);if((O=($=p.result)==null?void 0:$.chunk)!=null&&O.content){const m=N(p.result.chunk.content,b);m&&(yield{text:m,done:!0})}}}catch{}}catch(l){l.name==="AbortError"?yield{text:"Connection timed out. Please check if the server is running.",done:!0}:l.name==="TypeError"&&l.message.includes("Failed to fetch")?yield{text:"Could not connect to the server. Please check if the server is running.",done:!0}:yield{text:`Error: ${l.message}`,done:!0}}}function N(t,e){return e&&t.length>e.length&&t.startsWith(e)?t.slice(e.length):t}async function te(t){const e=w(),n=await fetch(`${e}/v1/chat`,X(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Z(t))}));if(!n.ok){const o=await n.text();throw new Error(`Network response was not ok: ${n.status} ${o}`)}const r=await n.json();if(r.error)throw new Error(`MCP Error: ${r.error.message}`);return r}exports.configureApi=_;exports.initializeChatbot=H;exports.sendToolsRequest=te;exports.streamChat=ee;
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// 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\n// Store the configured API URL, key, and session ID\nlet configuredApiUrl: string | null = null;\nlet configuredApiKey: string | null = null;\nlet configuredSessionId: string | 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 if (!apiUrl || typeof apiUrl !== 'string') {\n throw new Error('API URL must be a valid string');\n }\n if (apiKey !== null && typeof apiKey !== 'string') {\n throw new Error('API key must be a valid string or null');\n }\n if (sessionId !== null && typeof sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n configuredApiUrl = apiUrl;\n configuredApiKey = apiKey;\n configuredSessionId = sessionId;\n}\n\n// Get the configured API URL or throw an error if not configured\nconst getApiUrl = (): string => {\n if (!configuredApiUrl) {\n throw new Error('API URL not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n return configuredApiUrl;\n};\n\n// Get the configured API key or return null if not configured\nconst getApiKey = (): string | null => {\n return configuredApiKey;\n};\n\n// Get the configured session ID or return null if not configured\nconst getSessionId = (): string | null => {\n return configuredSessionId;\n};\n\n// Helper to get fetch options with connection pooling if available\nconst getFetchOptions = (apiUrl: string, options: RequestInit = {}): RequestInit | any => {\n const isHttps = apiUrl.startsWith('https:');\n \n // Only use agents in Node.js environment\n if (typeof window === 'undefined') {\n if (isHttps && httpsAgent) {\n return { ...options, agent: httpsAgent } as any;\n } else if (httpAgent) {\n return { ...options, agent: httpAgent } as any;\n }\n }\n \n // Browser environment\n const requestId = Date.now().toString(36) + Math.random().toString(36).substring(2);\n \n // Use keep-alive header in browser environments\n const headers: Record<string, string> = {\n 'Connection': 'keep-alive',\n 'X-Request-ID': requestId\n };\n \n // Add API key to headers only if it exists\n const apiKey = getApiKey();\n if (apiKey) {\n headers['X-API-Key'] = apiKey;\n }\n \n // Add session ID to headers only if it exists\n const sessionId = getSessionId();\n if (sessionId) {\n headers['X-Session-ID'] = sessionId;\n }\n \n return {\n ...options,\n headers: {\n ...options.headers,\n ...headers\n }\n };\n};\n\n// Create MCP request\nconst 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\nconst 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\nexport async function* streamChat(\n message: string,\n stream: boolean = true\n): AsyncGenerator<StreamResponse> {\n try {\n const API_URL = getApiUrl();\n \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(`${API_URL}/v1/chat`, {\n ...getFetchOptions(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': stream ? 'text/event-stream' : 'application/json'\n },\n body: JSON.stringify(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 currentFullText = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const chunk = decoder.decode(value, { stream: true });\n buffer += chunk;\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.trim() && line.startsWith('data: ')) {\n try {\n const jsonText = line.slice(6).trim();\n if (jsonText === '[DONE]') {\n yield { text: '', done: true };\n break;\n }\n\n const data = JSON.parse(jsonText) as MCPResponse;\n \n if (data.result) {\n let content = '';\n \n if (data.result.type === 'start') {\n continue;\n } else if (data.result.type === 'chunk' && data.result.chunk) {\n content = data.result.chunk.content;\n } else if (data.result.type === 'complete' && data.result.output?.messages?.[0]) {\n content = data.result.output.messages[0].content;\n }\n\n if (content) {\n const newText = extractNewText(content, currentFullText);\n if (newText) {\n currentFullText += newText;\n yield {\n text: newText,\n done: data.result.type === 'complete'\n };\n } else if (data.result.type === 'complete') {\n yield { text: '', done: true };\n }\n }\n }\n } catch (error) {\n console.warn('Error parsing JSON chunk:', line, 'Error:', error);\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n // Handle any remaining buffer\n if (buffer && buffer.startsWith('data: ')) {\n try {\n const jsonText = buffer.slice(6).trim();\n if (jsonText !== '[DONE]') {\n const data = JSON.parse(jsonText) as MCPResponse;\n if (data.result?.chunk?.content) {\n const newText = extractNewText(data.result.chunk.content, currentFullText);\n if (newText) {\n yield {\n text: newText,\n done: data.result.type === 'complete'\n };\n }\n }\n }\n } catch (error) {\n console.warn('Error parsing final JSON buffer:', buffer, 'Error:', error);\n }\n }\n } catch (error: any) {\n if (error.name === 'AbortError') {\n yield { \n text: 'Connection timed out. Please check if the server is running.', \n done: true \n };\n } else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n yield { \n text: 'Could not connect to the server. Please check if the server is running.', \n done: true \n };\n } else {\n yield { \n text: `Error: ${error.message}`, \n done: true \n };\n }\n }\n}\n\n// Helper function to extract only new text from incoming chunks\nfunction extractNewText(incomingText: string, currentText: string): string {\n if (!currentText) return incomingText;\n if (currentText.endsWith(incomingText)) return '';\n \n if (incomingText.length > currentText.length) {\n if (incomingText.startsWith(currentText)) {\n return incomingText.slice(currentText.length);\n }\n \n let i = 0;\n const minLength = Math.min(currentText.length, incomingText.length);\n while (i < minLength && currentText[i] === incomingText[i]) {\n i++;\n }\n \n if (i > currentText.length / 2) {\n return incomingText.slice(i);\n }\n }\n \n return incomingText;\n}\n\n// New function to send tools request\nexport async function sendToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): Promise<MCPResponse> {\n const API_URL = getApiUrl();\n \n const response = await fetch(`${API_URL}/v1/chat`, getFetchOptions(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(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}"],"names":["configuredApiUrl","configuredApiKey","configuredSessionId","configureApi","apiUrl","apiKey","sessionId","getApiUrl","getApiKey","getSessionId","getFetchOptions","options","headers","createMCPRequest","message","stream","createMCPToolsRequest","tools","streamChat","API_URL","controller","timeoutId","response","errorText","data","_d","_c","_b","_a","reader","_e","decoder","buffer","currentFullText","done","value","chunk","lines","line","jsonText","content","_g","_f","newText","extractNewText","error","_i","_h","incomingText","currentText","i","minLength","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// 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\n// Store the configured API URL, key, and session ID\nlet configuredApiUrl: string | null = null;\nlet configuredApiKey: string | null = null;\nlet configuredSessionId: string | null = null;\n\n// Temporary key management\nlet sessionId: string | null = null;\nlet keyRefreshTimer: number | null = null;\n\n// Key Exchange Response interface\ninterface KeyExchangeResponse {\n temporaryKey: string;\n sessionId: string;\n expiresIn: number; // seconds\n expiresAt: number; // timestamp\n}\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 if (!apiUrl || typeof apiUrl !== 'string') {\n throw new Error('API URL must be a valid string');\n }\n if (apiKey !== null && typeof apiKey !== 'string') {\n throw new Error('API key must be a valid string or null');\n }\n if (sessionId !== null && typeof sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n configuredApiUrl = apiUrl;\n configuredApiKey = apiKey;\n configuredSessionId = sessionId;\n}\n\n// Get the configured API URL or throw an error if not configured\nconst getApiUrl = (): string => {\n if (!configuredApiUrl) {\n throw new Error('API URL not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n return configuredApiUrl;\n};\n\n// Get the configured API key or return null if not configured\nconst getApiKey = (): string | null => {\n return configuredApiKey;\n};\n\n// Get the configured session ID or return null if not configured\nconst getSessionId = (): string | null => {\n return configuredSessionId;\n};\n\n// Initialize chatbot with temporary key exchange\nexport const initializeChatbot = async (permanentApiKey: string, customOrigin?: string): Promise<void> => {\n try {\n const API_URL = getApiUrl();\n \n // Exchange permanent key for temporary session key\n const response = await fetch(`${API_URL}/api/v1/exchange-key`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n apiKey: permanentApiKey,\n origin: customOrigin || (typeof window !== 'undefined' ? window.location.origin : 'node-client')\n })\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to exchange API key: ${response.status} ${errorText}`);\n }\n \n const data: KeyExchangeResponse = await response.json();\n \n // Store only the temporary key and session\n sessionId = data.sessionId;\n configuredApiKey = data.temporaryKey; // Use temporary key as the main API key\n configuredSessionId = data.sessionId;\n \n // Clear permanent key from memory (security measure)\n permanentApiKey = '';\n \n // Set up auto-refresh (90% of expiry time)\n const refreshInterval = data.expiresIn * 0.9 * 1000;\n if (keyRefreshTimer) {\n clearTimeout(keyRefreshTimer);\n }\n keyRefreshTimer = setTimeout(() => refreshTemporaryKey(), refreshInterval) as any; \n } catch (error) {\n throw error;\n }\n};\n\n// Refresh temporary key before it expires\nconst refreshTemporaryKey = async (): Promise<void> => {\n if (!sessionId) return;\n \n try {\n const API_URL = getApiUrl();\n \n const response = await fetch(`${API_URL}/api/v1/refresh-key`, {\n method: 'POST',\n headers: { \n 'Content-Type': 'application/json',\n 'X-Session-ID': sessionId,\n 'Origin': typeof window !== 'undefined' ? window.location.origin : 'node-client'\n }\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to refresh key: ${response.status} ${errorText}`);\n }\n \n const data: KeyExchangeResponse = await response.json();\n \n // Update keys\n configuredApiKey = data.temporaryKey;\n \n // Reset timer\n if (keyRefreshTimer) {\n clearTimeout(keyRefreshTimer);\n }\n const refreshInterval = data.expiresIn * 0.9 * 1000;\n keyRefreshTimer = setTimeout(() => refreshTemporaryKey(), refreshInterval) as any;\n } catch (error) {\n // Emit event for handling by consumer\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('chatbot:auth:failed', { detail: error }));\n }\n }\n};\n\n// Helper to get fetch options with connection pooling and enhanced security\nconst getFetchOptions = (apiUrl: string, options: RequestInit = {}): RequestInit | any => {\n const isHttps = apiUrl.startsWith('https:');\n \n // Only use agents in Node.js environment\n if (typeof window === 'undefined') {\n if (isHttps && httpsAgent) {\n return { ...options, agent: httpsAgent } as any;\n } else if (httpAgent) {\n return { ...options, agent: httpAgent } as any;\n }\n }\n \n // Browser environment with enhanced security headers\n const requestId = Date.now().toString(36) + Math.random().toString(36).substring(2);\n const timestamp = Date.now();\n \n // Enhanced security headers\n const headers: Record<string, string> = {\n 'Connection': 'keep-alive',\n 'X-Request-ID': requestId,\n 'X-Timestamp': timestamp.toString()\n };\n \n // Add origin and referrer for security validation\n if (typeof window !== 'undefined') {\n headers['X-Origin'] = window.location.origin;\n headers['X-Referrer'] = document.referrer || 'direct';\n }\n \n // Add API key to headers only if it exists\n const apiKey = getApiKey();\n if (apiKey) {\n headers['X-API-Key'] = apiKey;\n \n // Add request signature for enhanced security\n if (typeof window !== 'undefined') {\n headers['X-Signature'] = generateRequestSignature(\n requestId,\n timestamp,\n options.body\n );\n }\n }\n \n // Add session ID to headers only if it exists\n const sessionId = getSessionId();\n if (sessionId) {\n headers['X-Session-ID'] = sessionId;\n }\n \n return {\n ...options,\n headers: {\n ...options.headers,\n ...headers\n }\n };\n};\n\n// Generate request signature for enhanced security\nconst generateRequestSignature = (\n requestId: string, \n timestamp: number, \n body?: any\n): string => {\n const payload = `${requestId}:${timestamp}:${body ? JSON.stringify(body) : ''}`;\n // Simple base64 encoding - in production, you should use HMAC\n return btoa(payload).substring(0, 16);\n};\n\n// Rate limiter implementation\nclass RateLimiter {\n private requests: Map<string, number[]> = new Map();\n \n canMakeRequest(\n identifier: string, \n maxRequests: number = 20, \n windowMs: number = 60000\n ): boolean {\n const now = Date.now();\n const userRequests = this.requests.get(identifier) || [];\n const recentRequests = userRequests.filter(time => now - time < windowMs);\n \n if (recentRequests.length >= maxRequests) {\n return false;\n }\n \n recentRequests.push(now);\n this.requests.set(identifier, recentRequests);\n \n // Cleanup old entries\n if (this.requests.size > 1000) {\n this.cleanup(windowMs);\n }\n \n return true;\n }\n \n private cleanup(windowMs: number): void {\n const now = Date.now();\n for (const [key, requests] of this.requests.entries()) {\n const recent = requests.filter(time => now - time < windowMs);\n if (recent.length === 0) {\n this.requests.delete(key);\n } else {\n this.requests.set(key, recent);\n }\n }\n }\n}\n\n// Global rate limiter instance\nconst rateLimiter = new RateLimiter();\n\n// Security monitoring (client-side)\nconst securityMonitor = {\n config: {\n monitoring: {\n enabled: true\n }\n },\n\n async loadConfig(): Promise<void> {\n try {\n const API_URL = getApiUrl();\n const response = await fetch(`${API_URL}/api/v1/security/config`);\n if (response.ok) {\n const config = await response.json();\n if (config.monitoring) {\n this.config.monitoring = {\n ...this.config.monitoring,\n ...config.monitoring\n };\n }\n }\n } catch (e) {\n // Fail silently, use default config\n }\n },\n\n detectDevTools(): boolean {\n if (typeof window === 'undefined') return false;\n const threshold = 160;\n return (window.outerHeight - window.innerHeight > threshold) || \n (window.outerWidth - window.innerWidth > threshold);\n },\n \n async init(): Promise<void> {\n if (typeof window === 'undefined') return;\n \n // Load configuration first\n await this.loadConfig();\n }\n};\n\n// Initialize security monitoring if in browser\nif (typeof window !== 'undefined') {\n securityMonitor.init().catch(() => {\n // Fail silently, security monitoring will use default config\n });\n}\n\n// Create MCP request\nconst 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\nconst 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\nexport async function* streamChat(\n message: string,\n stream: boolean = true\n): AsyncGenerator<StreamResponse> {\n try {\n // Check rate limiting\n const sessionIdentifier = getSessionId() || 'anonymous';\n \n if (!rateLimiter.canMakeRequest(sessionIdentifier, 20, 60000)) {\n yield { \n text: 'Rate limit exceeded. Please wait a moment before sending more messages.', \n done: true \n };\n return;\n }\n \n const API_URL = getApiUrl();\n \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(`${API_URL}/v1/chat`, {\n ...getFetchOptions(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': stream ? 'text/event-stream' : 'application/json'\n },\n body: JSON.stringify(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 currentFullText = '';\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 try {\n const jsonText = line.slice(6).trim();\n \n // Check for [DONE] message (legacy format)\n if (jsonText === '[DONE]') {\n yield { text: '', done: true };\n return;\n }\n\n // Skip empty data lines\n if (!jsonText) {\n continue;\n }\n\n const data = JSON.parse(jsonText) as MCPResponse;\n \n // Handle errors\n if (data.error) {\n throw new Error(`MCP Error: ${data.error.message}`);\n }\n \n let content = '';\n let isDone = false;\n \n // Handle MCP protocol format\n if (data.result) {\n if (data.result.type === 'start') {\n continue;\n } else if (data.result.type === 'chunk' && data.result.chunk) {\n content = data.result.chunk.content;\n } else if (data.result.type === 'complete' && data.result.output?.messages?.[0]) {\n // For complete messages, only yield if we haven't received any content yet\n if (!hasReceivedContent) {\n content = data.result.output.messages[0].content;\n isDone = true;\n } else {\n // Skip the complete message if we've already received chunks\n continue;\n }\n }\n }\n \n // Handle direct server response format (from LLM clients)\n // This is what the server actually sends: { \"response\": \"...\", \"done\": false/true }\n if (!content && 'response' in data && typeof data.response === 'string') {\n content = data.response;\n }\n \n // Check for done signal in the data\n if ('done' in data && data.done === true) {\n isDone = true;\n }\n\n if (content) {\n const newText = extractNewText(content, currentFullText);\n if (newText) {\n currentFullText += newText;\n hasReceivedContent = true;\n yield {\n text: newText,\n done: isDone\n };\n }\n }\n \n // If we received a done signal, exit\n if (isDone) {\n if (!hasReceivedContent) {\n // Yield empty response to indicate completion\n yield { text: '', done: true };\n }\n return;\n }\n } catch (parseError) {\n // Don't throw, just continue processing\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 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 // Handle any remaining buffer (fallback)\n if (buffer && buffer.startsWith('data: ')) {\n try {\n const jsonText = buffer.slice(6).trim();\n if (jsonText && jsonText !== '[DONE]') {\n const data = JSON.parse(jsonText) as MCPResponse;\n if (data.result?.chunk?.content) {\n const newText = extractNewText(data.result.chunk.content, currentFullText);\n if (newText) {\n yield {\n text: newText,\n done: true\n };\n }\n }\n }\n } catch (error) {\n // Fail silently for final buffer parsing\n }\n }\n \n } catch (error: any) {\n if (error.name === 'AbortError') {\n yield { \n text: 'Connection timed out. Please check if the server is running.', \n done: true \n };\n } else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n yield { \n text: 'Could not connect to the server. Please check if the server is running.', \n done: true \n };\n } else {\n yield { \n text: `Error: ${error.message}`, \n done: true \n };\n }\n }\n}\n\n// Helper function to extract only new text from incoming chunks\nfunction extractNewText(incomingText: string, currentText: string): string {\n // Simplified version - just check if we have new content at the end\n if (!currentText) return incomingText;\n \n // If incoming text is longer and starts with current text, return the new part\n if (incomingText.length > currentText.length && incomingText.startsWith(currentText)) {\n return incomingText.slice(currentText.length);\n }\n \n // Otherwise return the full incoming text (fallback)\n return incomingText;\n}\n\n// New function to send tools request\nexport async function sendToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): Promise<MCPResponse> {\n const API_URL = getApiUrl();\n \n const response = await fetch(`${API_URL}/v1/chat`, getFetchOptions(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(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}"],"names":["configuredApiUrl","configuredApiKey","configuredSessionId","sessionId","keyRefreshTimer","configureApi","apiUrl","apiKey","getApiUrl","getApiKey","getSessionId","initializeChatbot","permanentApiKey","customOrigin","API_URL","response","errorText","data","refreshInterval","refreshTemporaryKey","error","getFetchOptions","options","requestId","timestamp","headers","generateRequestSignature","body","payload","RateLimiter","__publicField","identifier","maxRequests","windowMs","now","recentRequests","time","key","requests","recent","rateLimiter","securityMonitor","config","threshold","createMCPRequest","message","stream","createMCPToolsRequest","tools","streamChat","sessionIdentifier","controller","timeoutId","_d","_c","_b","_a","reader","_e","decoder","buffer","currentFullText","hasReceivedContent","done","value","chunk","lineStartIndex","newlineIndex","line","jsonText","content","isDone","_g","_f","newText","extractNewText","_i","_h","incomingText","currentText","sendToolsRequest"],"mappings":"oPAyDA,IAAIA,EAAkC,KAClCC,EAAkC,KAClCC,EAAqC,KAGrCC,EAA2B,KAC3BC,EAAiC,KAW9B,MAAMC,EAAe,CAACC,EAAgBC,EAAwB,KAAMJ,EAA2B,OAAe,CACnH,GAAI,CAACG,GAAU,OAAOA,GAAW,SACzB,MAAA,IAAI,MAAM,gCAAgC,EAElD,GAAIC,IAAW,MAAQ,OAAOA,GAAW,SACjC,MAAA,IAAI,MAAM,wCAAwC,EAE1D,GAAIJ,IAAc,MAAQ,OAAOA,GAAc,SACvC,MAAA,IAAI,MAAM,2CAA2C,EAE1CH,EAAAM,EACAL,EAAAM,EACGJ,EAAAA,CACxB,EAGMK,EAAY,IAAc,CAC9B,GAAI,CAACR,EACG,MAAA,IAAI,MAAM,yGAAyG,EAEpH,OAAAA,CACT,EAGMS,EAAY,IACTR,EAIHS,EAAe,IACZR,EAIIS,EAAoB,MAAOC,EAAyBC,IAAyC,CACpG,GAAA,CACF,MAAMC,EAAUN,EAAU,EAGpBO,EAAW,MAAM,MAAM,GAAGD,CAAO,uBAAwB,CAC7D,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CACnB,OAAQF,EACR,OAAQC,IAAiB,OAAO,OAAW,IAAc,OAAO,SAAS,OAAS,cACnF,CAAA,CAAA,CACF,EAEG,GAAA,CAACE,EAAS,GAAI,CACV,MAAAC,EAAY,MAAMD,EAAS,KAAK,EACtC,MAAM,IAAI,MAAM,+BAA+BA,EAAS,MAAM,IAAIC,CAAS,EAAE,CAAA,CAGzE,MAAAC,EAA4B,MAAMF,EAAS,KAAK,EAGtDZ,EAAYc,EAAK,UACjBhB,EAAmBgB,EAAK,aACxBf,EAAsBe,EAAK,UAGTL,EAAA,GAGZ,MAAAM,EAAkBD,EAAK,UAAY,GAAM,IAC3Cb,GACF,aAAaA,CAAe,EAE9BA,EAAkB,WAAW,IAAMe,EAAoB,EAAGD,CAAe,QAClEE,EAAO,CACR,MAAAA,CAAA,CAEV,EAGMD,EAAsB,SAA2B,CACrD,GAAKhB,EAED,GAAA,CACF,MAAMW,EAAUN,EAAU,EAEpBO,EAAW,MAAM,MAAM,GAAGD,CAAO,sBAAuB,CAC5D,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,eAAgBX,EAChB,OAAU,OAAO,OAAW,IAAc,OAAO,SAAS,OAAS,aAAA,CACrE,CACD,EAEG,GAAA,CAACY,EAAS,GAAI,CACV,MAAAC,EAAY,MAAMD,EAAS,KAAK,EACtC,MAAM,IAAI,MAAM,0BAA0BA,EAAS,MAAM,IAAIC,CAAS,EAAE,CAAA,CAGpE,MAAAC,EAA4B,MAAMF,EAAS,KAAK,EAGtDd,EAAmBgB,EAAK,aAGpBb,GACF,aAAaA,CAAe,EAExB,MAAAc,EAAkBD,EAAK,UAAY,GAAM,IAC/Cb,EAAkB,WAAW,IAAMe,EAAoB,EAAGD,CAAe,QAClEE,EAAO,CAEV,OAAO,OAAW,KACb,OAAA,cAAc,IAAI,YAAY,sBAAuB,CAAE,OAAQA,CAAA,CAAO,CAAC,CAChF,CAEJ,EAGMC,EAAkB,CAACf,EAAgBgB,EAAuB,KAA0B,CACxEhB,EAAO,WAAW,QAAQ,EAY1C,MAAMiB,EAAY,KAAK,IAAI,EAAE,SAAS,EAAE,EAAI,KAAK,OAAS,EAAA,SAAS,EAAE,EAAE,UAAU,CAAC,EAC5EC,EAAY,KAAK,IAAI,EAGrBC,EAAkC,CACtC,WAAc,aACd,eAAgBF,EAChB,cAAeC,EAAU,SAAS,CACpC,EAGI,OAAO,OAAW,MACZC,EAAA,UAAU,EAAI,OAAO,SAAS,OAC9BA,EAAA,YAAY,EAAI,SAAS,UAAY,UAI/C,MAAMlB,EAASE,EAAU,EACrBF,IACFkB,EAAQ,WAAW,EAAIlB,EAGnB,OAAO,OAAW,MACpBkB,EAAQ,aAAa,EAAIC,EACvBH,EACAC,EACAF,EAAQ,IACV,IAKJ,MAAMnB,EAAYO,EAAa,EAC/B,OAAIP,IACFsB,EAAQ,cAAc,EAAItB,GAGrB,CACL,GAAGmB,EACH,QAAS,CACP,GAAGA,EAAQ,QACX,GAAGG,CAAA,CAEP,CACF,EAGMC,EAA2B,CAC/BH,EACAC,EACAG,IACW,CACL,MAAAC,EAAU,GAAGL,CAAS,IAAIC,CAAS,IAAIG,EAAO,KAAK,UAAUA,CAAI,EAAI,EAAE,GAE7E,OAAO,KAAKC,CAAO,EAAE,UAAU,EAAG,EAAE,CACtC,EAGA,MAAMC,CAAY,CAAlB,cACUC,EAAA,oBAAsC,KAE9C,eACEC,EACAC,EAAsB,GACtBC,EAAmB,IACV,CACH,MAAAC,EAAM,KAAK,IAAI,EAEfC,GADe,KAAK,SAAS,IAAIJ,CAAU,GAAK,CAAC,GACnB,OAAeK,GAAAF,EAAME,EAAOH,CAAQ,EAEpE,OAAAE,EAAe,QAAUH,EACpB,IAGTG,EAAe,KAAKD,CAAG,EAClB,KAAA,SAAS,IAAIH,EAAYI,CAAc,EAGxC,KAAK,SAAS,KAAO,KACvB,KAAK,QAAQF,CAAQ,EAGhB,GAAA,CAGD,QAAQA,EAAwB,CAChC,MAAAC,EAAM,KAAK,IAAI,EACrB,SAAW,CAACG,EAAKC,CAAQ,IAAK,KAAK,SAAS,UAAW,CACrD,MAAMC,EAASD,EAAS,OAAeF,GAAAF,EAAME,EAAOH,CAAQ,EACxDM,EAAO,SAAW,EACf,KAAA,SAAS,OAAOF,CAAG,EAEnB,KAAA,SAAS,IAAIA,EAAKE,CAAM,CAC/B,CACF,CAEJ,CAGA,MAAMC,EAAc,IAAIX,EAGlBY,EAAkB,CACtB,OAAQ,CACN,WAAY,CACV,QAAS,EAAA,CAEb,EAEA,MAAM,YAA4B,CAC5B,GAAA,CACF,MAAM3B,EAAUN,EAAU,EACpBO,EAAW,MAAM,MAAM,GAAGD,CAAO,yBAAyB,EAChE,GAAIC,EAAS,GAAI,CACT,MAAA2B,EAAS,MAAM3B,EAAS,KAAK,EAC/B2B,EAAO,aACT,KAAK,OAAO,WAAa,CACvB,GAAG,KAAK,OAAO,WACf,GAAGA,EAAO,UACZ,EACF,OAEQ,CAAA,CAGd,EAEA,gBAA0B,CACpB,GAAA,OAAO,OAAW,IAAoB,MAAA,GAC1C,MAAMC,EAAY,IACV,OAAA,OAAO,YAAc,OAAO,YAAcA,GAC1C,OAAO,WAAa,OAAO,WAAaA,CAClD,EAEA,MAAM,MAAsB,CACtB,OAAO,OAAW,KAGtB,MAAM,KAAK,WAAW,CAAA,CAE1B,EAGI,OAAO,OAAW,KACJF,EAAA,OAAO,MAAM,IAAM,CAAA,CAElC,EAIH,MAAMG,EAAmB,CAACC,EAAiBC,EAAkB,MACpD,CACL,QAAS,MACT,OAAQ,aACR,OAAQ,CACN,KAAM,OACN,UAAW,CACT,SAAU,CACR,CAAE,KAAM,OAAQ,QAASD,CAAQ,CACnC,EACA,OAAAC,CAAA,CAEJ,EACA,GAAI,KAAK,MAAM,SAAS,EAAE,EAAI,KAAK,OAAS,EAAA,SAAS,EAAE,EAAE,UAAU,CAAC,CACtE,GAIIC,EAAyBC,IACtB,CACL,QAAS,MACT,OAAQ,aACR,OAAQ,CACN,KAAM,QACN,UAAW,CACT,MAAAA,CAAA,CAEJ,EACA,GAAI,KAAK,MAAM,SAAS,EAAE,EAAI,KAAK,OAAS,EAAA,SAAS,EAAE,EAAE,UAAU,CAAC,CACtE,GAGqB,eAAAC,GACrBJ,EACAC,EAAkB,GACc,uBAC5B,GAAA,CAEI,MAAAI,EAAoBxC,KAAkB,YAE5C,GAAI,CAAC8B,EAAY,eAAeU,EAAmB,GAAI,GAAK,EAAG,CACvD,KAAA,CACJ,KAAM,0EACN,KAAM,EACR,EACA,MAAA,CAGF,MAAMpC,EAAUN,EAAU,EAGpB2C,EAAa,IAAI,gBACjBC,EAAY,WAAW,IAAMD,EAAW,MAAA,EAAS,GAAK,EAEtDpC,EAAW,MAAM,MAAM,GAAGD,CAAO,WAAY,CACjD,GAAGO,EAAgBP,EAAS,CAC1B,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,OAAUgC,EAAS,oBAAsB,kBAC3C,EACA,KAAM,KAAK,UAAUF,EAAiBC,EAASC,CAAM,CAAC,CAAA,CACvD,EACD,OAAQK,EAAW,MAAA,CACpB,EAIG,GAFJ,aAAaC,CAAS,EAElB,CAACrC,EAAS,GAAI,CACV,MAAAC,EAAY,MAAMD,EAAS,KAAK,EACtC,MAAM,IAAI,MAAM,gCAAgCA,EAAS,MAAM,IAAIC,CAAS,EAAE,CAAA,CAGhF,GAAI,CAAC8B,EAAQ,CAEL,MAAA7B,EAAO,MAAMF,EAAS,KAAK,EACjC,GAAIE,EAAK,MACP,MAAM,IAAI,MAAM,cAAcA,EAAK,MAAM,OAAO,EAAE,GAEhDoC,GAAAC,GAAAC,GAAAC,EAAAvC,EAAK,SAAL,YAAAuC,EAAa,SAAb,YAAAD,EAAqB,WAArB,YAAAD,EAAgC,KAAhC,MAAAD,EAAoC,UAChC,KAAA,CACJ,KAAMpC,EAAK,OAAO,OAAO,SAAS,CAAC,EAAE,QACrC,KAAM,EACR,GAEF,MAAA,CAGI,MAAAwC,GAASC,EAAA3C,EAAS,OAAT,YAAA2C,EAAe,YAC9B,GAAI,CAACD,EAAc,MAAA,IAAI,MAAM,qBAAqB,EAE5C,MAAAE,EAAU,IAAI,YACpB,IAAIC,EAAS,GACTC,EAAkB,GAClBC,EAAqB,GAErB,GAAA,CACF,OAAa,CACX,KAAM,CAAE,KAAAC,EAAM,MAAAC,CAAU,EAAA,MAAMP,EAAO,KAAK,EAC1C,GAAIM,EACF,MAGF,MAAME,EAAQN,EAAQ,OAAOK,EAAO,CAAE,OAAQ,GAAM,EAC1CJ,GAAAK,EAGV,IAAIC,EAAiB,EACjBC,EAEJ,MAAQA,EAAeP,EAAO,QAAQ;AAAA,EAAMM,CAAc,KAAO,IAAI,CACnE,MAAME,EAAOR,EAAO,MAAMM,EAAgBC,CAAY,EAAE,KAAK,EAG7D,GAFAD,EAAiBC,EAAe,EAE5BC,GAAQA,EAAK,WAAW,QAAQ,EAC9B,GAAA,CACF,MAAMC,EAAWD,EAAK,MAAM,CAAC,EAAE,KAAK,EAGpC,GAAIC,IAAa,SAAU,CACzB,KAAM,CAAE,KAAM,GAAI,KAAM,EAAK,EAC7B,MAAA,CAIF,GAAI,CAACA,EACH,SAGI,MAAApD,EAAO,KAAK,MAAMoD,CAAQ,EAGhC,GAAIpD,EAAK,MACP,MAAM,IAAI,MAAM,cAAcA,EAAK,MAAM,OAAO,EAAE,EAGpD,IAAIqD,EAAU,GACVC,EAAS,GAGb,GAAItD,EAAK,OAAQ,CACX,GAAAA,EAAK,OAAO,OAAS,QACvB,YACSA,EAAK,OAAO,OAAS,SAAWA,EAAK,OAAO,MAC3CqD,EAAArD,EAAK,OAAO,MAAM,gBACnBA,EAAK,OAAO,OAAS,cAAcuD,GAAAC,EAAAxD,EAAK,OAAO,SAAZ,YAAAwD,EAAoB,WAApB,MAAAD,EAA+B,IAE3E,GAAI,CAACV,EACHQ,EAAUrD,EAAK,OAAO,OAAO,SAAS,CAAC,EAAE,QAChCsD,EAAA,OAGT,SAEJ,CAcF,GATI,CAACD,GAAW,aAAcrD,GAAQ,OAAOA,EAAK,UAAa,WAC7DqD,EAAUrD,EAAK,UAIb,SAAUA,GAAQA,EAAK,OAAS,KACzBsD,EAAA,IAGPD,EAAS,CACL,MAAAI,EAAUC,EAAeL,EAAST,CAAe,EACnDa,IACiBb,GAAAa,EACEZ,EAAA,GACf,KAAA,CACJ,KAAMY,EACN,KAAMH,CACR,EACF,CAIF,GAAIA,EAAQ,CACLT,IAEH,KAAM,CAAE,KAAM,GAAI,KAAM,EAAK,GAE/B,MAAA,OAEiB,CAAA,CAGvB,CAIOF,EAAAA,EAAO,MAAMM,CAAc,EAGhCN,EAAO,OAAS,MACTA,EAAAA,EAAO,MAAM,IAAO,EAC/B,CAIEE,IACF,KAAM,CAAE,KAAM,GAAI,KAAM,EAAK,EAC/B,QAEA,CACAL,EAAO,YAAY,CAAA,CAIrB,GAAIG,GAAUA,EAAO,WAAW,QAAQ,EAClC,GAAA,CACF,MAAMS,EAAWT,EAAO,MAAM,CAAC,EAAE,KAAK,EAClC,GAAAS,GAAYA,IAAa,SAAU,CAC/B,MAAApD,EAAO,KAAK,MAAMoD,CAAQ,EAC5B,IAAAO,GAAAC,EAAA5D,EAAK,SAAL,YAAA4D,EAAa,QAAb,MAAAD,EAAoB,QAAS,CAC/B,MAAMF,EAAUC,EAAe1D,EAAK,OAAO,MAAM,QAAS4C,CAAe,EACrEa,IACI,KAAA,CACJ,KAAMA,EACN,KAAM,EACR,EACF,CACF,OAEY,CAAA,QAKXtD,EAAY,CACfA,EAAM,OAAS,aACX,KAAA,CACJ,KAAM,+DACN,KAAM,EACR,EACSA,EAAM,OAAS,aAAeA,EAAM,QAAQ,SAAS,iBAAiB,EACzE,KAAA,CACJ,KAAM,0EACN,KAAM,EACR,EAEM,KAAA,CACJ,KAAM,UAAUA,EAAM,OAAO,GAC7B,KAAM,EACR,CACF,CAEJ,CAGA,SAASuD,EAAeG,EAAsBC,EAA6B,CAErE,OAACA,GAGDD,EAAa,OAASC,EAAY,QAAUD,EAAa,WAAWC,CAAW,EAC1ED,EAAa,MAAMC,EAAY,MAAM,EAJrBD,CAS3B,CAGA,eAAsBE,GAAiBhC,EAAuF,CAC5H,MAAMlC,EAAUN,EAAU,EAEpBO,EAAW,MAAM,MAAM,GAAGD,CAAO,WAAYO,EAAgBP,EAAS,CAC1E,OAAQ,OACR,QAAS,CACP,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAUiC,EAAsBC,CAAK,CAAC,CAAA,CAClD,CAAC,EAEE,GAAA,CAACjC,EAAS,GAAI,CACV,MAAAC,EAAY,MAAMD,EAAS,KAAK,EACtC,MAAM,IAAI,MAAM,gCAAgCA,EAAS,MAAM,IAAIC,CAAS,EAAE,CAAA,CAG1E,MAAAC,EAAO,MAAMF,EAAS,KAAK,EACjC,GAAIE,EAAK,MACP,MAAM,IAAI,MAAM,cAAcA,EAAK,MAAM,OAAO,EAAE,EAG7C,OAAAA,CACT"}
package/dist/api.mjs CHANGED
@@ -1,32 +1,135 @@
1
- let k = null, C = null, O = null;
2
- const J = (t, e = null, r = null) => {
1
+ var F = Object.defineProperty;
2
+ var K = (t, e, n) => e in t ? F(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n;
3
+ var N = (t, e, n) => K(t, typeof e != "symbol" ? e + "" : e, n);
4
+ let v = null, S = null, q = null, $ = null, f = null;
5
+ const Z = (t, e = null, n = null) => {
3
6
  if (!t || typeof t != "string")
4
7
  throw new Error("API URL must be a valid string");
5
8
  if (e !== null && typeof e != "string")
6
9
  throw new Error("API key must be a valid string or null");
7
- if (r !== null && typeof r != "string")
10
+ if (n !== null && typeof n != "string")
8
11
  throw new Error("Session ID must be a valid string or null");
9
- k = t, C = e, O = r;
10
- }, R = () => {
11
- if (!k)
12
+ v = t, S = e, q = n;
13
+ }, w = () => {
14
+ if (!v)
12
15
  throw new Error("API URL not configured. Please call configureApi() with your server URL before using any API functions.");
13
- return k;
14
- }, M = () => C, x = () => O, j = (t, e = {}) => {
16
+ return v;
17
+ }, _ = () => S, M = () => q, ee = async (t, e) => {
18
+ try {
19
+ const n = w(), r = await fetch(`${n}/api/v1/exchange-key`, {
20
+ method: "POST",
21
+ headers: { "Content-Type": "application/json" },
22
+ body: JSON.stringify({
23
+ apiKey: t,
24
+ origin: e || (typeof window < "u" ? window.location.origin : "node-client")
25
+ })
26
+ });
27
+ if (!r.ok) {
28
+ const i = await r.text();
29
+ throw new Error(`Failed to exchange API key: ${r.status} ${i}`);
30
+ }
31
+ const o = await r.json();
32
+ $ = o.sessionId, S = o.temporaryKey, q = o.sessionId, t = "";
33
+ const c = o.expiresIn * 0.9 * 1e3;
34
+ f && clearTimeout(f), f = setTimeout(() => U(), c);
35
+ } catch (n) {
36
+ throw n;
37
+ }
38
+ }, U = async () => {
39
+ if ($)
40
+ try {
41
+ const t = w(), e = await fetch(`${t}/api/v1/refresh-key`, {
42
+ method: "POST",
43
+ headers: {
44
+ "Content-Type": "application/json",
45
+ "X-Session-ID": $,
46
+ Origin: typeof window < "u" ? window.location.origin : "node-client"
47
+ }
48
+ });
49
+ if (!e.ok) {
50
+ const o = await e.text();
51
+ throw new Error(`Failed to refresh key: ${e.status} ${o}`);
52
+ }
53
+ const n = await e.json();
54
+ S = n.temporaryKey, f && clearTimeout(f);
55
+ const r = n.expiresIn * 0.9 * 1e3;
56
+ f = setTimeout(() => U(), r);
57
+ } catch (t) {
58
+ typeof window < "u" && window.dispatchEvent(new CustomEvent("chatbot:auth:failed", { detail: t }));
59
+ }
60
+ }, X = (t, e = {}) => {
15
61
  t.startsWith("https:");
16
- const o = {
62
+ const n = Date.now().toString(36) + Math.random().toString(36).substring(2), r = Date.now(), o = {
17
63
  Connection: "keep-alive",
18
- "X-Request-ID": Date.now().toString(36) + Math.random().toString(36).substring(2)
19
- }, i = M();
20
- i && (o["X-API-Key"] = i);
21
- const c = x();
22
- return c && (o["X-Session-ID"] = c), {
64
+ "X-Request-ID": n,
65
+ "X-Timestamp": r.toString()
66
+ };
67
+ typeof window < "u" && (o["X-Origin"] = window.location.origin, o["X-Referrer"] = document.referrer || "direct");
68
+ const c = _();
69
+ c && (o["X-API-Key"] = c, typeof window < "u" && (o["X-Signature"] = z(
70
+ n,
71
+ r,
72
+ e.body
73
+ )));
74
+ const i = M();
75
+ return i && (o["X-Session-ID"] = i), {
23
76
  ...e,
24
77
  headers: {
25
78
  ...e.headers,
26
79
  ...o
27
80
  }
28
81
  };
29
- }, L = (t, e = !0) => ({
82
+ }, z = (t, e, n) => {
83
+ const r = `${t}:${e}:${n ? JSON.stringify(n) : ""}`;
84
+ return btoa(r).substring(0, 16);
85
+ };
86
+ class H {
87
+ constructor() {
88
+ N(this, "requests", /* @__PURE__ */ new Map());
89
+ }
90
+ canMakeRequest(e, n = 20, r = 6e4) {
91
+ const o = Date.now(), i = (this.requests.get(e) || []).filter((g) => o - g < r);
92
+ return i.length >= n ? !1 : (i.push(o), this.requests.set(e, i), this.requests.size > 1e3 && this.cleanup(r), !0);
93
+ }
94
+ cleanup(e) {
95
+ const n = Date.now();
96
+ for (const [r, o] of this.requests.entries()) {
97
+ const c = o.filter((i) => n - i < e);
98
+ c.length === 0 ? this.requests.delete(r) : this.requests.set(r, c);
99
+ }
100
+ }
101
+ }
102
+ const B = new H(), G = {
103
+ config: {
104
+ monitoring: {
105
+ enabled: !0
106
+ }
107
+ },
108
+ async loadConfig() {
109
+ try {
110
+ const t = w(), e = await fetch(`${t}/api/v1/security/config`);
111
+ if (e.ok) {
112
+ const n = await e.json();
113
+ n.monitoring && (this.config.monitoring = {
114
+ ...this.config.monitoring,
115
+ ...n.monitoring
116
+ });
117
+ }
118
+ } catch {
119
+ }
120
+ },
121
+ detectDevTools() {
122
+ if (typeof window > "u") return !1;
123
+ const t = 160;
124
+ return window.outerHeight - window.innerHeight > t || window.outerWidth - window.innerWidth > t;
125
+ },
126
+ async init() {
127
+ typeof window > "u" || await this.loadConfig();
128
+ }
129
+ };
130
+ typeof window < "u" && G.init().catch(() => {
131
+ });
132
+ const Q = (t, e = !0) => ({
30
133
  jsonrpc: "2.0",
31
134
  method: "tools/call",
32
135
  params: {
@@ -39,7 +142,7 @@ const J = (t, e = null, r = null) => {
39
142
  }
40
143
  },
41
144
  id: Date.now().toString(36) + Math.random().toString(36).substring(2)
42
- }), q = (t) => ({
145
+ }), V = (t) => ({
43
146
  jsonrpc: "2.0",
44
147
  method: "tools/call",
45
148
  params: {
@@ -50,139 +153,153 @@ const J = (t, e = null, r = null) => {
50
153
  },
51
154
  id: Date.now().toString(36) + Math.random().toString(36).substring(2)
52
155
  });
53
- async function* U(t, e = !0) {
54
- var r, o, i, c, E, b, S, A, P;
156
+ async function* te(t, e = !0) {
157
+ var n, r, o, c, i, g, A, C, O;
55
158
  try {
56
- const a = R(), I = new AbortController(), D = setTimeout(() => I.abort(), 6e4), u = await fetch(`${a}/v1/chat`, {
57
- ...j(a, {
159
+ const l = M() || "anonymous";
160
+ if (!B.canMakeRequest(l, 20, 6e4)) {
161
+ yield {
162
+ text: "Rate limit exceeded. Please wait a moment before sending more messages.",
163
+ done: !0
164
+ };
165
+ return;
166
+ }
167
+ const D = w(), j = new AbortController(), J = setTimeout(() => j.abort(), 6e4), h = await fetch(`${D}/v1/chat`, {
168
+ ...X(D, {
58
169
  method: "POST",
59
170
  headers: {
60
171
  "Content-Type": "application/json",
61
172
  Accept: e ? "text/event-stream" : "application/json"
62
173
  },
63
- body: JSON.stringify(L(t, e))
174
+ body: JSON.stringify(Q(t, e))
64
175
  }),
65
- signal: I.signal
176
+ signal: j.signal
66
177
  });
67
- if (clearTimeout(D), !u.ok) {
68
- const n = await u.text();
69
- throw new Error(`Network response was not ok: ${u.status} ${n}`);
178
+ if (clearTimeout(J), !h.ok) {
179
+ const a = await h.text();
180
+ throw new Error(`Network response was not ok: ${h.status} ${a}`);
70
181
  }
71
182
  if (!e) {
72
- const n = await u.json();
73
- if (n.error)
74
- throw new Error(`MCP Error: ${n.error.message}`);
75
- (c = (i = (o = (r = n.result) == null ? void 0 : r.output) == null ? void 0 : o.messages) == null ? void 0 : i[0]) != null && c.content && (yield {
76
- text: n.result.output.messages[0].content,
183
+ const a = await h.json();
184
+ if (a.error)
185
+ throw new Error(`MCP Error: ${a.error.message}`);
186
+ (c = (o = (r = (n = a.result) == null ? void 0 : n.output) == null ? void 0 : r.messages) == null ? void 0 : o[0]) != null && c.content && (yield {
187
+ text: a.result.output.messages[0].content,
77
188
  done: !0
78
189
  });
79
190
  return;
80
191
  }
81
- const w = (E = u.body) == null ? void 0 : E.getReader();
82
- if (!w) throw new Error("No reader available");
83
- const $ = new TextDecoder();
84
- let l = "", y = "";
192
+ const T = (i = h.body) == null ? void 0 : i.getReader();
193
+ if (!T) throw new Error("No reader available");
194
+ const W = new TextDecoder();
195
+ let u = "", P = "", p = !1;
85
196
  try {
86
197
  for (; ; ) {
87
- const { done: n, value: d } = await w.read();
88
- if (n) break;
89
- const f = $.decode(d, { stream: !0 });
90
- l += f;
91
- const v = l.split(`
92
- `);
93
- l = v.pop() || "";
94
- for (const h of v)
95
- if (h.trim() && h.startsWith("data: "))
198
+ const { done: a, value: y } = await T.read();
199
+ if (a)
200
+ break;
201
+ const m = W.decode(y, { stream: !0 });
202
+ u += m;
203
+ let k = 0, R;
204
+ for (; (R = u.indexOf(`
205
+ `, k)) !== -1; ) {
206
+ const b = u.slice(k, R).trim();
207
+ if (k = R + 1, b && b.startsWith("data: "))
96
208
  try {
97
- const p = h.slice(6).trim();
98
- if (p === "[DONE]") {
209
+ const x = b.slice(6).trim();
210
+ if (x === "[DONE]") {
99
211
  yield { text: "", done: !0 };
100
- break;
212
+ return;
101
213
  }
102
- const s = JSON.parse(p);
214
+ if (!x)
215
+ continue;
216
+ const s = JSON.parse(x);
217
+ if (s.error)
218
+ throw new Error(`MCP Error: ${s.error.message}`);
219
+ let d = "", I = !1;
103
220
  if (s.result) {
104
- let g = "";
105
221
  if (s.result.type === "start")
106
222
  continue;
107
- if (s.result.type === "chunk" && s.result.chunk ? g = s.result.chunk.content : s.result.type === "complete" && ((S = (b = s.result.output) == null ? void 0 : b.messages) != null && S[0]) && (g = s.result.output.messages[0].content), g) {
108
- const m = N(g, y);
109
- m ? (y += m, yield {
110
- text: m,
111
- done: s.result.type === "complete"
112
- }) : s.result.type === "complete" && (yield { text: "", done: !0 });
113
- }
223
+ if (s.result.type === "chunk" && s.result.chunk)
224
+ d = s.result.chunk.content;
225
+ else if (s.result.type === "complete" && ((A = (g = s.result.output) == null ? void 0 : g.messages) != null && A[0]))
226
+ if (!p)
227
+ d = s.result.output.messages[0].content, I = !0;
228
+ else
229
+ continue;
114
230
  }
115
- } catch (p) {
116
- console.warn("Error parsing JSON chunk:", h, "Error:", p);
231
+ if (!d && "response" in s && typeof s.response == "string" && (d = s.response), "done" in s && s.done === !0 && (I = !0), d) {
232
+ const E = L(d, P);
233
+ E && (P += E, p = !0, yield {
234
+ text: E,
235
+ done: I
236
+ });
237
+ }
238
+ if (I) {
239
+ p || (yield { text: "", done: !0 });
240
+ return;
241
+ }
242
+ } catch {
117
243
  }
244
+ }
245
+ u = u.slice(k), u.length > 1e6 && (u = u.slice(-5e5));
118
246
  }
247
+ p && (yield { text: "", done: !0 });
119
248
  } finally {
120
- w.releaseLock();
249
+ T.releaseLock();
121
250
  }
122
- if (l && l.startsWith("data: "))
251
+ if (u && u.startsWith("data: "))
123
252
  try {
124
- const n = l.slice(6).trim();
125
- if (n !== "[DONE]") {
126
- const d = JSON.parse(n);
127
- if ((P = (A = d.result) == null ? void 0 : A.chunk) != null && P.content) {
128
- const f = N(d.result.chunk.content, y);
129
- f && (yield {
130
- text: f,
131
- done: d.result.type === "complete"
253
+ const a = u.slice(6).trim();
254
+ if (a && a !== "[DONE]") {
255
+ const y = JSON.parse(a);
256
+ if ((O = (C = y.result) == null ? void 0 : C.chunk) != null && O.content) {
257
+ const m = L(y.result.chunk.content, P);
258
+ m && (yield {
259
+ text: m,
260
+ done: !0
132
261
  });
133
262
  }
134
263
  }
135
- } catch (n) {
136
- console.warn("Error parsing final JSON buffer:", l, "Error:", n);
264
+ } catch {
137
265
  }
138
- } catch (a) {
139
- a.name === "AbortError" ? yield {
266
+ } catch (l) {
267
+ l.name === "AbortError" ? yield {
140
268
  text: "Connection timed out. Please check if the server is running.",
141
269
  done: !0
142
- } : a.name === "TypeError" && a.message.includes("Failed to fetch") ? yield {
270
+ } : l.name === "TypeError" && l.message.includes("Failed to fetch") ? yield {
143
271
  text: "Could not connect to the server. Please check if the server is running.",
144
272
  done: !0
145
273
  } : yield {
146
- text: `Error: ${a.message}`,
274
+ text: `Error: ${l.message}`,
147
275
  done: !0
148
276
  };
149
277
  }
150
278
  }
151
- function N(t, e) {
152
- if (!e) return t;
153
- if (e.endsWith(t)) return "";
154
- if (t.length > e.length) {
155
- if (t.startsWith(e))
156
- return t.slice(e.length);
157
- let r = 0;
158
- const o = Math.min(e.length, t.length);
159
- for (; r < o && e[r] === t[r]; )
160
- r++;
161
- if (r > e.length / 2)
162
- return t.slice(r);
163
- }
164
- return t;
279
+ function L(t, e) {
280
+ return e && t.length > e.length && t.startsWith(e) ? t.slice(e.length) : t;
165
281
  }
166
- async function W(t) {
167
- const e = R(), r = await fetch(`${e}/v1/chat`, j(e, {
282
+ async function ne(t) {
283
+ const e = w(), n = await fetch(`${e}/v1/chat`, X(e, {
168
284
  method: "POST",
169
285
  headers: {
170
286
  "Content-Type": "application/json"
171
287
  },
172
- body: JSON.stringify(q(t))
288
+ body: JSON.stringify(V(t))
173
289
  }));
174
- if (!r.ok) {
175
- const i = await r.text();
176
- throw new Error(`Network response was not ok: ${r.status} ${i}`);
290
+ if (!n.ok) {
291
+ const o = await n.text();
292
+ throw new Error(`Network response was not ok: ${n.status} ${o}`);
177
293
  }
178
- const o = await r.json();
179
- if (o.error)
180
- throw new Error(`MCP Error: ${o.error.message}`);
181
- return o;
294
+ const r = await n.json();
295
+ if (r.error)
296
+ throw new Error(`MCP Error: ${r.error.message}`);
297
+ return r;
182
298
  }
183
299
  export {
184
- J as configureApi,
185
- W as sendToolsRequest,
186
- U as streamChat
300
+ Z as configureApi,
301
+ ee as initializeChatbot,
302
+ ne as sendToolsRequest,
303
+ te as streamChat
187
304
  };
188
305
  //# 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// 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\n// Store the configured API URL, key, and session ID\nlet configuredApiUrl: string | null = null;\nlet configuredApiKey: string | null = null;\nlet configuredSessionId: string | 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 if (!apiUrl || typeof apiUrl !== 'string') {\n throw new Error('API URL must be a valid string');\n }\n if (apiKey !== null && typeof apiKey !== 'string') {\n throw new Error('API key must be a valid string or null');\n }\n if (sessionId !== null && typeof sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n configuredApiUrl = apiUrl;\n configuredApiKey = apiKey;\n configuredSessionId = sessionId;\n}\n\n// Get the configured API URL or throw an error if not configured\nconst getApiUrl = (): string => {\n if (!configuredApiUrl) {\n throw new Error('API URL not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n return configuredApiUrl;\n};\n\n// Get the configured API key or return null if not configured\nconst getApiKey = (): string | null => {\n return configuredApiKey;\n};\n\n// Get the configured session ID or return null if not configured\nconst getSessionId = (): string | null => {\n return configuredSessionId;\n};\n\n// Helper to get fetch options with connection pooling if available\nconst getFetchOptions = (apiUrl: string, options: RequestInit = {}): RequestInit | any => {\n const isHttps = apiUrl.startsWith('https:');\n \n // Only use agents in Node.js environment\n if (typeof window === 'undefined') {\n if (isHttps && httpsAgent) {\n return { ...options, agent: httpsAgent } as any;\n } else if (httpAgent) {\n return { ...options, agent: httpAgent } as any;\n }\n }\n \n // Browser environment\n const requestId = Date.now().toString(36) + Math.random().toString(36).substring(2);\n \n // Use keep-alive header in browser environments\n const headers: Record<string, string> = {\n 'Connection': 'keep-alive',\n 'X-Request-ID': requestId\n };\n \n // Add API key to headers only if it exists\n const apiKey = getApiKey();\n if (apiKey) {\n headers['X-API-Key'] = apiKey;\n }\n \n // Add session ID to headers only if it exists\n const sessionId = getSessionId();\n if (sessionId) {\n headers['X-Session-ID'] = sessionId;\n }\n \n return {\n ...options,\n headers: {\n ...options.headers,\n ...headers\n }\n };\n};\n\n// Create MCP request\nconst 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\nconst 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\nexport async function* streamChat(\n message: string,\n stream: boolean = true\n): AsyncGenerator<StreamResponse> {\n try {\n const API_URL = getApiUrl();\n \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(`${API_URL}/v1/chat`, {\n ...getFetchOptions(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': stream ? 'text/event-stream' : 'application/json'\n },\n body: JSON.stringify(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 currentFullText = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const chunk = decoder.decode(value, { stream: true });\n buffer += chunk;\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.trim() && line.startsWith('data: ')) {\n try {\n const jsonText = line.slice(6).trim();\n if (jsonText === '[DONE]') {\n yield { text: '', done: true };\n break;\n }\n\n const data = JSON.parse(jsonText) as MCPResponse;\n \n if (data.result) {\n let content = '';\n \n if (data.result.type === 'start') {\n continue;\n } else if (data.result.type === 'chunk' && data.result.chunk) {\n content = data.result.chunk.content;\n } else if (data.result.type === 'complete' && data.result.output?.messages?.[0]) {\n content = data.result.output.messages[0].content;\n }\n\n if (content) {\n const newText = extractNewText(content, currentFullText);\n if (newText) {\n currentFullText += newText;\n yield {\n text: newText,\n done: data.result.type === 'complete'\n };\n } else if (data.result.type === 'complete') {\n yield { text: '', done: true };\n }\n }\n }\n } catch (error) {\n console.warn('Error parsing JSON chunk:', line, 'Error:', error);\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n // Handle any remaining buffer\n if (buffer && buffer.startsWith('data: ')) {\n try {\n const jsonText = buffer.slice(6).trim();\n if (jsonText !== '[DONE]') {\n const data = JSON.parse(jsonText) as MCPResponse;\n if (data.result?.chunk?.content) {\n const newText = extractNewText(data.result.chunk.content, currentFullText);\n if (newText) {\n yield {\n text: newText,\n done: data.result.type === 'complete'\n };\n }\n }\n }\n } catch (error) {\n console.warn('Error parsing final JSON buffer:', buffer, 'Error:', error);\n }\n }\n } catch (error: any) {\n if (error.name === 'AbortError') {\n yield { \n text: 'Connection timed out. Please check if the server is running.', \n done: true \n };\n } else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n yield { \n text: 'Could not connect to the server. Please check if the server is running.', \n done: true \n };\n } else {\n yield { \n text: `Error: ${error.message}`, \n done: true \n };\n }\n }\n}\n\n// Helper function to extract only new text from incoming chunks\nfunction extractNewText(incomingText: string, currentText: string): string {\n if (!currentText) return incomingText;\n if (currentText.endsWith(incomingText)) return '';\n \n if (incomingText.length > currentText.length) {\n if (incomingText.startsWith(currentText)) {\n return incomingText.slice(currentText.length);\n }\n \n let i = 0;\n const minLength = Math.min(currentText.length, incomingText.length);\n while (i < minLength && currentText[i] === incomingText[i]) {\n i++;\n }\n \n if (i > currentText.length / 2) {\n return incomingText.slice(i);\n }\n }\n \n return incomingText;\n}\n\n// New function to send tools request\nexport async function sendToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): Promise<MCPResponse> {\n const API_URL = getApiUrl();\n \n const response = await fetch(`${API_URL}/v1/chat`, getFetchOptions(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(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}"],"names":["configuredApiUrl","configuredApiKey","configuredSessionId","configureApi","apiUrl","apiKey","sessionId","getApiUrl","getApiKey","getSessionId","getFetchOptions","options","headers","createMCPRequest","message","stream","createMCPToolsRequest","tools","streamChat","_a","_b","_c","_d","_e","_f","_g","_h","_i","API_URL","controller","timeoutId","response","errorText","data","reader","decoder","buffer","currentFullText","done","value","chunk","lines","line","jsonText","content","newText","extractNewText","error","incomingText","currentText","i","minLength","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// 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\n// Store the configured API URL, key, and session ID\nlet configuredApiUrl: string | null = null;\nlet configuredApiKey: string | null = null;\nlet configuredSessionId: string | null = null;\n\n// Temporary key management\nlet sessionId: string | null = null;\nlet keyRefreshTimer: number | null = null;\n\n// Key Exchange Response interface\ninterface KeyExchangeResponse {\n temporaryKey: string;\n sessionId: string;\n expiresIn: number; // seconds\n expiresAt: number; // timestamp\n}\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 if (!apiUrl || typeof apiUrl !== 'string') {\n throw new Error('API URL must be a valid string');\n }\n if (apiKey !== null && typeof apiKey !== 'string') {\n throw new Error('API key must be a valid string or null');\n }\n if (sessionId !== null && typeof sessionId !== 'string') {\n throw new Error('Session ID must be a valid string or null');\n }\n configuredApiUrl = apiUrl;\n configuredApiKey = apiKey;\n configuredSessionId = sessionId;\n}\n\n// Get the configured API URL or throw an error if not configured\nconst getApiUrl = (): string => {\n if (!configuredApiUrl) {\n throw new Error('API URL not configured. Please call configureApi() with your server URL before using any API functions.');\n }\n return configuredApiUrl;\n};\n\n// Get the configured API key or return null if not configured\nconst getApiKey = (): string | null => {\n return configuredApiKey;\n};\n\n// Get the configured session ID or return null if not configured\nconst getSessionId = (): string | null => {\n return configuredSessionId;\n};\n\n// Initialize chatbot with temporary key exchange\nexport const initializeChatbot = async (permanentApiKey: string, customOrigin?: string): Promise<void> => {\n try {\n const API_URL = getApiUrl();\n \n // Exchange permanent key for temporary session key\n const response = await fetch(`${API_URL}/api/v1/exchange-key`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n apiKey: permanentApiKey,\n origin: customOrigin || (typeof window !== 'undefined' ? window.location.origin : 'node-client')\n })\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to exchange API key: ${response.status} ${errorText}`);\n }\n \n const data: KeyExchangeResponse = await response.json();\n \n // Store only the temporary key and session\n sessionId = data.sessionId;\n configuredApiKey = data.temporaryKey; // Use temporary key as the main API key\n configuredSessionId = data.sessionId;\n \n // Clear permanent key from memory (security measure)\n permanentApiKey = '';\n \n // Set up auto-refresh (90% of expiry time)\n const refreshInterval = data.expiresIn * 0.9 * 1000;\n if (keyRefreshTimer) {\n clearTimeout(keyRefreshTimer);\n }\n keyRefreshTimer = setTimeout(() => refreshTemporaryKey(), refreshInterval) as any; \n } catch (error) {\n throw error;\n }\n};\n\n// Refresh temporary key before it expires\nconst refreshTemporaryKey = async (): Promise<void> => {\n if (!sessionId) return;\n \n try {\n const API_URL = getApiUrl();\n \n const response = await fetch(`${API_URL}/api/v1/refresh-key`, {\n method: 'POST',\n headers: { \n 'Content-Type': 'application/json',\n 'X-Session-ID': sessionId,\n 'Origin': typeof window !== 'undefined' ? window.location.origin : 'node-client'\n }\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to refresh key: ${response.status} ${errorText}`);\n }\n \n const data: KeyExchangeResponse = await response.json();\n \n // Update keys\n configuredApiKey = data.temporaryKey;\n \n // Reset timer\n if (keyRefreshTimer) {\n clearTimeout(keyRefreshTimer);\n }\n const refreshInterval = data.expiresIn * 0.9 * 1000;\n keyRefreshTimer = setTimeout(() => refreshTemporaryKey(), refreshInterval) as any;\n } catch (error) {\n // Emit event for handling by consumer\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('chatbot:auth:failed', { detail: error }));\n }\n }\n};\n\n// Helper to get fetch options with connection pooling and enhanced security\nconst getFetchOptions = (apiUrl: string, options: RequestInit = {}): RequestInit | any => {\n const isHttps = apiUrl.startsWith('https:');\n \n // Only use agents in Node.js environment\n if (typeof window === 'undefined') {\n if (isHttps && httpsAgent) {\n return { ...options, agent: httpsAgent } as any;\n } else if (httpAgent) {\n return { ...options, agent: httpAgent } as any;\n }\n }\n \n // Browser environment with enhanced security headers\n const requestId = Date.now().toString(36) + Math.random().toString(36).substring(2);\n const timestamp = Date.now();\n \n // Enhanced security headers\n const headers: Record<string, string> = {\n 'Connection': 'keep-alive',\n 'X-Request-ID': requestId,\n 'X-Timestamp': timestamp.toString()\n };\n \n // Add origin and referrer for security validation\n if (typeof window !== 'undefined') {\n headers['X-Origin'] = window.location.origin;\n headers['X-Referrer'] = document.referrer || 'direct';\n }\n \n // Add API key to headers only if it exists\n const apiKey = getApiKey();\n if (apiKey) {\n headers['X-API-Key'] = apiKey;\n \n // Add request signature for enhanced security\n if (typeof window !== 'undefined') {\n headers['X-Signature'] = generateRequestSignature(\n requestId,\n timestamp,\n options.body\n );\n }\n }\n \n // Add session ID to headers only if it exists\n const sessionId = getSessionId();\n if (sessionId) {\n headers['X-Session-ID'] = sessionId;\n }\n \n return {\n ...options,\n headers: {\n ...options.headers,\n ...headers\n }\n };\n};\n\n// Generate request signature for enhanced security\nconst generateRequestSignature = (\n requestId: string, \n timestamp: number, \n body?: any\n): string => {\n const payload = `${requestId}:${timestamp}:${body ? JSON.stringify(body) : ''}`;\n // Simple base64 encoding - in production, you should use HMAC\n return btoa(payload).substring(0, 16);\n};\n\n// Rate limiter implementation\nclass RateLimiter {\n private requests: Map<string, number[]> = new Map();\n \n canMakeRequest(\n identifier: string, \n maxRequests: number = 20, \n windowMs: number = 60000\n ): boolean {\n const now = Date.now();\n const userRequests = this.requests.get(identifier) || [];\n const recentRequests = userRequests.filter(time => now - time < windowMs);\n \n if (recentRequests.length >= maxRequests) {\n return false;\n }\n \n recentRequests.push(now);\n this.requests.set(identifier, recentRequests);\n \n // Cleanup old entries\n if (this.requests.size > 1000) {\n this.cleanup(windowMs);\n }\n \n return true;\n }\n \n private cleanup(windowMs: number): void {\n const now = Date.now();\n for (const [key, requests] of this.requests.entries()) {\n const recent = requests.filter(time => now - time < windowMs);\n if (recent.length === 0) {\n this.requests.delete(key);\n } else {\n this.requests.set(key, recent);\n }\n }\n }\n}\n\n// Global rate limiter instance\nconst rateLimiter = new RateLimiter();\n\n// Security monitoring (client-side)\nconst securityMonitor = {\n config: {\n monitoring: {\n enabled: true\n }\n },\n\n async loadConfig(): Promise<void> {\n try {\n const API_URL = getApiUrl();\n const response = await fetch(`${API_URL}/api/v1/security/config`);\n if (response.ok) {\n const config = await response.json();\n if (config.monitoring) {\n this.config.monitoring = {\n ...this.config.monitoring,\n ...config.monitoring\n };\n }\n }\n } catch (e) {\n // Fail silently, use default config\n }\n },\n\n detectDevTools(): boolean {\n if (typeof window === 'undefined') return false;\n const threshold = 160;\n return (window.outerHeight - window.innerHeight > threshold) || \n (window.outerWidth - window.innerWidth > threshold);\n },\n \n async init(): Promise<void> {\n if (typeof window === 'undefined') return;\n \n // Load configuration first\n await this.loadConfig();\n }\n};\n\n// Initialize security monitoring if in browser\nif (typeof window !== 'undefined') {\n securityMonitor.init().catch(() => {\n // Fail silently, security monitoring will use default config\n });\n}\n\n// Create MCP request\nconst 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\nconst 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\nexport async function* streamChat(\n message: string,\n stream: boolean = true\n): AsyncGenerator<StreamResponse> {\n try {\n // Check rate limiting\n const sessionIdentifier = getSessionId() || 'anonymous';\n \n if (!rateLimiter.canMakeRequest(sessionIdentifier, 20, 60000)) {\n yield { \n text: 'Rate limit exceeded. Please wait a moment before sending more messages.', \n done: true \n };\n return;\n }\n \n const API_URL = getApiUrl();\n \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(`${API_URL}/v1/chat`, {\n ...getFetchOptions(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': stream ? 'text/event-stream' : 'application/json'\n },\n body: JSON.stringify(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 currentFullText = '';\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 try {\n const jsonText = line.slice(6).trim();\n \n // Check for [DONE] message (legacy format)\n if (jsonText === '[DONE]') {\n yield { text: '', done: true };\n return;\n }\n\n // Skip empty data lines\n if (!jsonText) {\n continue;\n }\n\n const data = JSON.parse(jsonText) as MCPResponse;\n \n // Handle errors\n if (data.error) {\n throw new Error(`MCP Error: ${data.error.message}`);\n }\n \n let content = '';\n let isDone = false;\n \n // Handle MCP protocol format\n if (data.result) {\n if (data.result.type === 'start') {\n continue;\n } else if (data.result.type === 'chunk' && data.result.chunk) {\n content = data.result.chunk.content;\n } else if (data.result.type === 'complete' && data.result.output?.messages?.[0]) {\n // For complete messages, only yield if we haven't received any content yet\n if (!hasReceivedContent) {\n content = data.result.output.messages[0].content;\n isDone = true;\n } else {\n // Skip the complete message if we've already received chunks\n continue;\n }\n }\n }\n \n // Handle direct server response format (from LLM clients)\n // This is what the server actually sends: { \"response\": \"...\", \"done\": false/true }\n if (!content && 'response' in data && typeof data.response === 'string') {\n content = data.response;\n }\n \n // Check for done signal in the data\n if ('done' in data && data.done === true) {\n isDone = true;\n }\n\n if (content) {\n const newText = extractNewText(content, currentFullText);\n if (newText) {\n currentFullText += newText;\n hasReceivedContent = true;\n yield {\n text: newText,\n done: isDone\n };\n }\n }\n \n // If we received a done signal, exit\n if (isDone) {\n if (!hasReceivedContent) {\n // Yield empty response to indicate completion\n yield { text: '', done: true };\n }\n return;\n }\n } catch (parseError) {\n // Don't throw, just continue processing\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 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 // Handle any remaining buffer (fallback)\n if (buffer && buffer.startsWith('data: ')) {\n try {\n const jsonText = buffer.slice(6).trim();\n if (jsonText && jsonText !== '[DONE]') {\n const data = JSON.parse(jsonText) as MCPResponse;\n if (data.result?.chunk?.content) {\n const newText = extractNewText(data.result.chunk.content, currentFullText);\n if (newText) {\n yield {\n text: newText,\n done: true\n };\n }\n }\n }\n } catch (error) {\n // Fail silently for final buffer parsing\n }\n }\n \n } catch (error: any) {\n if (error.name === 'AbortError') {\n yield { \n text: 'Connection timed out. Please check if the server is running.', \n done: true \n };\n } else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {\n yield { \n text: 'Could not connect to the server. Please check if the server is running.', \n done: true \n };\n } else {\n yield { \n text: `Error: ${error.message}`, \n done: true \n };\n }\n }\n}\n\n// Helper function to extract only new text from incoming chunks\nfunction extractNewText(incomingText: string, currentText: string): string {\n // Simplified version - just check if we have new content at the end\n if (!currentText) return incomingText;\n \n // If incoming text is longer and starts with current text, return the new part\n if (incomingText.length > currentText.length && incomingText.startsWith(currentText)) {\n return incomingText.slice(currentText.length);\n }\n \n // Otherwise return the full incoming text (fallback)\n return incomingText;\n}\n\n// New function to send tools request\nexport async function sendToolsRequest(tools: Array<{ name: string; parameters: Record<string, any> }>): Promise<MCPResponse> {\n const API_URL = getApiUrl();\n \n const response = await fetch(`${API_URL}/v1/chat`, getFetchOptions(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(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}"],"names":["configuredApiUrl","configuredApiKey","configuredSessionId","sessionId","keyRefreshTimer","configureApi","apiUrl","apiKey","getApiUrl","getApiKey","getSessionId","initializeChatbot","permanentApiKey","customOrigin","API_URL","response","errorText","data","refreshInterval","refreshTemporaryKey","error","getFetchOptions","options","requestId","timestamp","headers","generateRequestSignature","body","payload","RateLimiter","__publicField","identifier","maxRequests","windowMs","now","recentRequests","time","key","requests","recent","rateLimiter","securityMonitor","config","threshold","createMCPRequest","message","stream","createMCPToolsRequest","tools","streamChat","_a","_b","_c","_d","_e","_f","_g","_h","_i","sessionIdentifier","controller","timeoutId","reader","decoder","buffer","currentFullText","hasReceivedContent","done","value","chunk","lineStartIndex","newlineIndex","line","jsonText","content","isDone","newText","extractNewText","incomingText","currentText","sendToolsRequest"],"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.4.4",
4
+ "version": "0.5.0",
5
5
  "description": "API client for the ORBIT MCP server",
6
6
  "type": "module",
7
7
  "main": "./dist/api.cjs",