@apukone/client 0.0.1 → 0.0.2
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 +2 -2
- package/index.d.ts +7 -7
- package/index.js +166 -154
- package/package.json +29 -29
package/README.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
# Apukone Client
|
|
2
|
-
|
|
1
|
+
# Apukone Client
|
|
2
|
+
|
|
3
3
|
Apukone client allows you to connect your agents and LLMs to Apukone platform.
|
package/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export interface ApukoneClientOptions {
|
|
2
|
-
host: string;
|
|
3
|
-
token: string;
|
|
4
|
-
onMessage: (messages: any[]) => Promise<any>;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export declare const ApukoneClient: (options: ApukoneClientOptions) => void;
|
|
1
|
+
export interface ApukoneClientOptions {
|
|
2
|
+
host: string;
|
|
3
|
+
token: string;
|
|
4
|
+
onMessage: (messages: any[]) => Promise<any>;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export declare const ApukoneClient: (options: ApukoneClientOptions) => void;
|
package/index.js
CHANGED
|
@@ -1,154 +1,166 @@
|
|
|
1
|
-
import http2 from 'http2';
|
|
2
|
-
|
|
3
|
-
export const ApukoneClient = ({ host, token, onMessage }) => {
|
|
4
|
-
const MESSAGE_ENDPOINT = `/api/agents/messages`;
|
|
5
|
-
|
|
6
|
-
let client;
|
|
7
|
-
let req;
|
|
8
|
-
let reconnectTimer;
|
|
9
|
-
const RECONNECT_DELAY = 1000;
|
|
10
|
-
|
|
11
|
-
const connectSSE = () => {
|
|
12
|
-
console.log(`Connecting to SSE at ${host}...`);
|
|
13
|
-
|
|
14
|
-
client = http2.connect(`${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,
|
|
25
|
-
'accept': 'text/event-stream',
|
|
26
|
-
'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
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
postReq.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
req.end()
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
1
|
+
import http2 from 'http2';
|
|
2
|
+
|
|
3
|
+
export const ApukoneClient = ({ host, token, onMessage }) => {
|
|
4
|
+
const MESSAGE_ENDPOINT = `/api/agents/messages`;
|
|
5
|
+
|
|
6
|
+
let client;
|
|
7
|
+
let req;
|
|
8
|
+
let reconnectTimer;
|
|
9
|
+
const RECONNECT_DELAY = 1000;
|
|
10
|
+
|
|
11
|
+
const connectSSE = () => {
|
|
12
|
+
console.log(`Connecting to SSE at ${host}...`);
|
|
13
|
+
|
|
14
|
+
client = http2.connect(`${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,
|
|
25
|
+
'accept': 'text/event-stream',
|
|
26
|
+
'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 startTime = Date.now();
|
|
71
|
+
const processedMessage = await onMessage(messages);
|
|
72
|
+
const inferenceTime = Date.now() - startTime;
|
|
73
|
+
|
|
74
|
+
let tokens = undefined;
|
|
75
|
+
// Check if message has token usage info (optional convention)
|
|
76
|
+
if (processedMessage && typeof processedMessage === 'object' && processedMessage.usage?.tokens) {
|
|
77
|
+
tokens = processedMessage.usage.tokens;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Send response via HTTP/2 stream
|
|
81
|
+
try {
|
|
82
|
+
const responseBody = JSON.stringify({
|
|
83
|
+
chat_id,
|
|
84
|
+
agent_id,
|
|
85
|
+
message: processedMessage,
|
|
86
|
+
stats: {
|
|
87
|
+
inferenceTime,
|
|
88
|
+
tokens
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
const responseBuffer = Buffer.from(responseBody);
|
|
92
|
+
|
|
93
|
+
const postReq = client.request({
|
|
94
|
+
':method': 'POST',
|
|
95
|
+
':path': '/api/inference/finalize',
|
|
96
|
+
'authorization': `Bearer ${token}`,
|
|
97
|
+
'content-type': 'application/json',
|
|
98
|
+
'content-length': responseBuffer.length
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
postReq.setEncoding('utf8');
|
|
102
|
+
postReq.on('response', (headers) => {
|
|
103
|
+
// console.log("Finalize response headers:", headers);
|
|
104
|
+
const status = headers[':status'];
|
|
105
|
+
if (status && status !== 200) {
|
|
106
|
+
console.error(`Error sending response: Status ${status}`);
|
|
107
|
+
// We can read body to see error message
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
postReq.on('data', (d) => {
|
|
111
|
+
// console.log("Finalize response data:", d);
|
|
112
|
+
});
|
|
113
|
+
postReq.on('end', () => {
|
|
114
|
+
console.log("Response sent successfully.");
|
|
115
|
+
});
|
|
116
|
+
postReq.on('error', (e) => {
|
|
117
|
+
console.error("Error sending response:", e);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
postReq.write(responseBuffer);
|
|
121
|
+
postReq.end();
|
|
122
|
+
|
|
123
|
+
} catch (e) {
|
|
124
|
+
console.error("Error creating response request:", e);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} catch (e) {
|
|
128
|
+
console.error("Error processing message:", e);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
req.on('end', () => {
|
|
135
|
+
console.log('Stream ended.');
|
|
136
|
+
cleanup();
|
|
137
|
+
scheduleReconnect();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
req.on('error', (err) => {
|
|
141
|
+
console.error('Stream error:', err);
|
|
142
|
+
cleanup();
|
|
143
|
+
scheduleReconnect();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
req.end();
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const cleanup = () => {
|
|
150
|
+
if (req) {
|
|
151
|
+
try { req.close(); } catch (e) { }
|
|
152
|
+
req = null;
|
|
153
|
+
}
|
|
154
|
+
if (client) {
|
|
155
|
+
try { client.close(); } catch (e) { }
|
|
156
|
+
client = null;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const scheduleReconnect = () => {
|
|
161
|
+
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
162
|
+
reconnectTimer = setTimeout(connectSSE, RECONNECT_DELAY);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
connectSSE();
|
|
166
|
+
};
|
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@apukone/client",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Apukone client allows you to connect your agents and LLMs to Apukone platform.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"AI",
|
|
7
|
-
"LLM",
|
|
8
|
-
"message",
|
|
9
|
-
"broker"
|
|
10
|
-
],
|
|
11
|
-
"license": "ISC",
|
|
12
|
-
"author": "Apukone",
|
|
13
|
-
"type": "module",
|
|
14
|
-
"main": "index.js",
|
|
15
|
-
"types": "index.d.ts",
|
|
16
|
-
"files": [
|
|
17
|
-
"index.js",
|
|
18
|
-
"index.d.ts"
|
|
19
|
-
],
|
|
20
|
-
"repository": {
|
|
21
|
-
"type": "git",
|
|
22
|
-
"url": "https://github.com/apukone/apukone-client.git"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"axios": "1.8.2"
|
|
26
|
-
},
|
|
27
|
-
"publishConfig": {
|
|
28
|
-
"access": "public"
|
|
29
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@apukone/client",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Apukone client allows you to connect your agents and LLMs to Apukone platform.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"AI",
|
|
7
|
+
"LLM",
|
|
8
|
+
"message",
|
|
9
|
+
"broker"
|
|
10
|
+
],
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"author": "Apukone",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "index.js",
|
|
15
|
+
"types": "index.d.ts",
|
|
16
|
+
"files": [
|
|
17
|
+
"index.js",
|
|
18
|
+
"index.d.ts"
|
|
19
|
+
],
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/apukone/apukone-client.git"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"axios": "1.8.2"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
}
|
|
30
30
|
}
|