@reititin/client 0.0.9 → 0.0.10

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.
Files changed (2) hide show
  1. package/index.js +129 -46
  2. package/package.json +28 -28
package/index.js CHANGED
@@ -1,71 +1,154 @@
1
1
  import http2 from 'http2';
2
- import axios from 'axios';
3
2
 
4
- export const ReititinClient = ({host, token, onMessage }) => {
3
+ export const ReititinClient = ({ host, token, onMessage }) => {
5
4
  const MESSAGE_ENDPOINT = `/api/agents/messages`;
6
- const FINALIZE_URL = `https://${host}/api/finalizeMessage`;
7
- let buffer = "";
5
+
6
+ let client;
7
+ let req;
8
+ let reconnectTimer;
9
+ const RECONNECT_DELAY = 1000;
8
10
 
9
11
  const connectSSE = () => {
10
- if (buffer) return;
11
-
12
- console.log("Waiting for messages.");
13
-
14
- const client = http2.connect(`https://${host}`);
15
- const req = client.request({
16
- ':method': 'GET',
17
- ':path': MESSAGE_ENDPOINT,
12
+ console.log(`Connecting to SSE at ${host}...`);
13
+
14
+ client = http2.connect(`http://${host}`);
15
+
16
+ client.on('error', (err) => {
17
+ console.error('Client error:', err);
18
+ cleanup();
19
+ scheduleReconnect();
20
+ });
21
+
22
+ req = client.request({
23
+ ':method': 'GET',
24
+ ':path': MESSAGE_ENDPOINT,
18
25
  'accept': 'text/event-stream',
19
26
  'authorization': `Bearer ${token}`
20
- }).setEncoding('utf8');
21
-
22
- req.on('data', chunk => buffer += chunk);
23
-
24
- req.on('end', async () => {
25
- try {
26
- const lines = buffer.split('\n').map(line => line.trim());
27
- const chat_id = lines.find(line => line.startsWith('chat_id:'))?.split(': ')[1];
28
- const agent_id = lines.find(line => line.startsWith('agent_id:'))?.split(': ')[1];
29
- const rawData = lines.find(line => line.startsWith('data:'))?.replace('data: ', '');
30
- if (onMessage && rawData && agent_id && chat_id) {
31
- console.log("Message received. Processing.");
32
- const processedMessage = await onMessage(JSON.parse(rawData));
33
- await axios.post(
34
- FINALIZE_URL,
35
- { chat_id, agent_id, message: processedMessage },
36
- {
37
- headers: {
38
- Authorization: `Bearer ${token}`
27
+ });
28
+
29
+ req.setEncoding('utf8');
30
+
31
+ let buffer = '';
32
+
33
+ req.on('data', async (chunk) => {
34
+ // console.log("Received chunk:", chunk);
35
+ // Uncomment for debugging
36
+
37
+ buffer += chunk;
38
+
39
+ // SSE events are separated by double newline
40
+ const parts = buffer.split('\n\n');
41
+ buffer = parts.pop(); // Keep the incomplete part in the buffer
42
+
43
+ for (const part of parts) {
44
+ if (!part.trim()) continue;
45
+
46
+ // Skip comments like ": connected"
47
+ if (part.startsWith(':')) continue;
48
+
49
+ const lines = part.split('\n');
50
+
51
+ const dataLine = lines.find(line => line.startsWith('data: '));
52
+ if (dataLine) {
53
+ const rawData = dataLine.substring(6); // remove "data: "
54
+ try {
55
+ const payload = JSON.parse(rawData);
56
+
57
+ const { agent_id, chat_id, content } = payload;
58
+
59
+ if (onMessage && agent_id && chat_id && content) {
60
+ console.log("Message received. Processing payload:", payload);
61
+
62
+ // The content from backend is a stringified JSON array of messages
63
+ let messages = [];
64
+ try {
65
+ messages = JSON.parse(content);
66
+ } catch (err) {
67
+ console.error("Failed to parse message content:", err);
68
+ }
69
+
70
+ const processedMessage = await onMessage(messages);
71
+
72
+ // Send response via HTTP/2 stream
73
+ try {
74
+ const responseBody = JSON.stringify({
75
+ chat_id,
76
+ agent_id,
77
+ message: processedMessage
78
+ });
79
+ const responseBuffer = Buffer.from(responseBody);
80
+
81
+ const postReq = client.request({
82
+ ':method': 'POST',
83
+ ':path': '/api/inference/finalize',
84
+ 'authorization': `Bearer ${token}`,
85
+ 'content-type': 'application/json',
86
+ 'content-length': responseBuffer.length
87
+ });
88
+
89
+ postReq.setEncoding('utf8');
90
+ postReq.on('response', (headers) => {
91
+ // console.log("Finalize response headers:", headers);
92
+ const status = headers[':status'];
93
+ if (status && status !== 200) {
94
+ console.error(`Error sending response: Status ${status}`);
95
+ // We can read body to see error message
96
+ }
97
+ });
98
+ postReq.on('data', (d) => {
99
+ // console.log("Finalize response data:", d);
100
+ });
101
+ postReq.on('end', () => {
102
+ console.log("Response sent successfully.");
103
+ });
104
+ postReq.on('error', (e) => {
105
+ console.error("Error sending response:", e);
106
+ });
107
+
108
+ postReq.write(responseBuffer);
109
+ postReq.end();
110
+
111
+ } catch (e) {
112
+ console.error("Error creating response request:", e);
39
113
  }
40
114
  }
41
- );
42
- console.log(`Response sent.`);
115
+ } catch (e) {
116
+ console.error("Error processing message:", e);
117
+ }
43
118
  }
44
- buffer = "";
45
- } catch(err) {
46
- console.log("Reconnecting.");
47
119
  }
48
- scheduleReconnect();
49
120
  });
50
121
 
51
- req.on('error', err => {
52
- console.error('Connection closed. Reconnecting.');
53
- req.close();
54
- client.close();
122
+ req.on('end', () => {
123
+ console.log('Stream ended.');
124
+ cleanup();
55
125
  scheduleReconnect();
56
126
  });
57
127
 
58
- req.on('timeout', err => {
59
- console.error('Connection timedout. Reconnecting.');
60
- req.close();
61
- client.close();
128
+ req.on('error', (err) => {
129
+ console.error('Stream error:', err);
130
+ cleanup();
62
131
  scheduleReconnect();
63
132
  });
64
133
 
65
134
  req.end();
66
135
  };
67
136
 
68
- const scheduleReconnect = () => setTimeout(connectSSE, 1000);
137
+ const cleanup = () => {
138
+ if (req) {
139
+ try { req.close(); } catch (e) { }
140
+ req = null;
141
+ }
142
+ if (client) {
143
+ try { client.close(); } catch (e) { }
144
+ client = null;
145
+ }
146
+ };
147
+
148
+ const scheduleReconnect = () => {
149
+ if (reconnectTimer) clearTimeout(reconnectTimer);
150
+ reconnectTimer = setTimeout(connectSSE, RECONNECT_DELAY);
151
+ };
69
152
 
70
153
  connectSSE();
71
154
  };
package/package.json CHANGED
@@ -1,28 +1,28 @@
1
- {
2
- "name": "@reititin/client",
3
- "version": "0.0.9",
4
- "description": "Reititin client allows you to connect your LLM system to Reititin platform.",
5
- "keywords": [
6
- "AI",
7
- "LLM",
8
- "message",
9
- "broker"
10
- ],
11
- "license": "ISC",
12
- "author": "Reititin",
13
- "type": "module",
14
- "main": "index.js",
15
- "files": [
16
- "index.js"
17
- ],
18
- "repository": {
19
- "type": "git",
20
- "url": "https://github.com/reititin/reititin-client.git"
21
- },
22
- "dependencies": {
23
- "axios": "1.8.2"
24
- },
25
- "publishConfig": {
26
- "access": "public"
27
- }
28
- }
1
+ {
2
+ "name": "@reititin/client",
3
+ "version": "0.0.10",
4
+ "description": "Reititin client allows you to connect your LLM system to Reititin platform.",
5
+ "keywords": [
6
+ "AI",
7
+ "LLM",
8
+ "message",
9
+ "broker"
10
+ ],
11
+ "license": "ISC",
12
+ "author": "Reititin",
13
+ "type": "module",
14
+ "main": "index.js",
15
+ "files": [
16
+ "index.js"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/reititin/reititin-client.git"
21
+ },
22
+ "dependencies": {
23
+ "axios": "1.8.2"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ }
28
+ }