@simfinity/constellation-client 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +66 -26
- package/dist/index.d.cts +44 -27
- package/dist/index.d.ts +44 -27
- package/dist/index.js +66 -26
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,26 +31,62 @@ var WebClient = class {
|
|
|
31
31
|
this.sessionId = null;
|
|
32
32
|
this.config = config;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Retrieve the list of available tools:
|
|
36
|
+
* Tools, or functions, can be exposed to & added to the model's context, allowing it
|
|
37
|
+
* to use them during the session as part of its response creation process. In order to add
|
|
38
|
+
* a tool to the session context, it must be listed (by name) at session creation time
|
|
39
|
+
* (see startSession(...) function)
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* Tools are remote functions exposed by MCP servers and integrated by the constellation server
|
|
43
|
+
*
|
|
44
|
+
* @exception
|
|
45
|
+
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
46
|
+
*/
|
|
47
|
+
async fetchAvailableTools() {
|
|
48
|
+
const response = await fetch(`${this.config.sessionEndpoint}/available_tools`, {
|
|
49
|
+
method: "GET",
|
|
50
|
+
headers: {
|
|
51
|
+
"Authorization": `Bearer ${this.config.key}`,
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
"Accept": "application/json"
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
throw new Error(`Could not fetch the list of available tools
|
|
58
|
+
[${response.status}:${response.statusText}]`);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const result = await response.json();
|
|
62
|
+
return result != null ? result : [];
|
|
63
|
+
} catch (error) {
|
|
64
|
+
throw `Failed to read session create response: ${error}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
34
67
|
/**
|
|
35
68
|
* Start a persistent chat room on the server, allowing for re-connection,
|
|
36
69
|
* when the streaming connection is lost. Once a session was started it must
|
|
37
70
|
* be closed to release the context on server side. See endSession().
|
|
38
71
|
*
|
|
39
72
|
* @remarks
|
|
40
|
-
* A session MUST exist to connect the stream.
|
|
73
|
+
* A session MUST exist first in order to connect the stream next.
|
|
41
74
|
*
|
|
42
|
-
* @param
|
|
43
|
-
* @param
|
|
75
|
+
* @param audioEnabled whether this session can receive & produce audio as well as text
|
|
76
|
+
* @param voiceName LLM specific voice name e.g. with OpenAI this could be 'alloy'
|
|
77
|
+
* @param tools a list of tool names to be included in this session. These must be matching the
|
|
78
|
+
* names returned by 'fetchAvailableTools()'.
|
|
44
79
|
*
|
|
45
80
|
* @exception
|
|
46
81
|
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* ```TypeScript
|
|
50
|
-
* await startSession("You are useful assistant", true)
|
|
51
|
-
* ```
|
|
52
82
|
*/
|
|
53
|
-
async startSession(
|
|
83
|
+
async startSession(audioEnabled, voiceName, tools = []) {
|
|
84
|
+
const prepareBody = {
|
|
85
|
+
llmProvider: this.config.llm,
|
|
86
|
+
audioEnabled,
|
|
87
|
+
voiceName,
|
|
88
|
+
includeTools: tools
|
|
89
|
+
};
|
|
54
90
|
const response = await fetch(`${this.config.sessionEndpoint}/prepare_session`, {
|
|
55
91
|
method: "POST",
|
|
56
92
|
headers: {
|
|
@@ -58,11 +94,7 @@ var WebClient = class {
|
|
|
58
94
|
"Content-Type": "application/json",
|
|
59
95
|
"Accept": "application/json"
|
|
60
96
|
},
|
|
61
|
-
body: JSON.stringify(
|
|
62
|
-
llmProvider: this.config.llm,
|
|
63
|
-
systemPrompt: instructions,
|
|
64
|
-
audio
|
|
65
|
-
})
|
|
97
|
+
body: JSON.stringify(prepareBody)
|
|
66
98
|
});
|
|
67
99
|
if (!response.ok) {
|
|
68
100
|
throw new Error(`Could not create a new chat session
|
|
@@ -116,7 +148,7 @@ var WebClient = class {
|
|
|
116
148
|
* This method not only opens a websocket connection with the server but also initiates a
|
|
117
149
|
* handshake, where the server explicitly acknowledges and accepts the client connection.
|
|
118
150
|
*
|
|
119
|
-
* @param audio for
|
|
151
|
+
* @param audio for an audio-enabled session, request this streaming connection to include audio events
|
|
120
152
|
* @param handlers callback functions to handle every possible communication events coming from the server
|
|
121
153
|
*
|
|
122
154
|
* @exception
|
|
@@ -125,7 +157,7 @@ var WebClient = class {
|
|
|
125
157
|
* @example
|
|
126
158
|
* ```TypeScript
|
|
127
159
|
* // Open an audio connection: in this example we choose to handle only audio data, and ignore text.
|
|
128
|
-
* await
|
|
160
|
+
* await joinSession(true, {
|
|
129
161
|
* onStreamClosed: (reason: string) => { console.log("Stream connection lost"); },
|
|
130
162
|
* onAudioResponseStart: () => { console.log("The model is talking"); },
|
|
131
163
|
* onAudioResponseChunk: (audioChunk: string) => { audioPlayer.enqueue(audioChunk); },
|
|
@@ -187,7 +219,7 @@ var WebClient = class {
|
|
|
187
219
|
this.ws = ws;
|
|
188
220
|
}
|
|
189
221
|
/**
|
|
190
|
-
*
|
|
222
|
+
* Once a session is joined: send a "system" update of the session settings.
|
|
191
223
|
* Allows to change some behavioral parameters like the temperature or system instructions.
|
|
192
224
|
* This does not trigger a model response.
|
|
193
225
|
*
|
|
@@ -195,16 +227,16 @@ var WebClient = class {
|
|
|
195
227
|
* With openai for example, this triggers (pseudo-code):
|
|
196
228
|
* webSocket.send({ type: "session.update", session: { ... }})
|
|
197
229
|
*
|
|
198
|
-
* @param settings
|
|
230
|
+
* @param settings new system settings to apply. Omitted values will remain unchanged
|
|
199
231
|
*
|
|
200
232
|
* @exception
|
|
201
233
|
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
202
234
|
*/
|
|
203
|
-
|
|
235
|
+
configureSession(settings) {
|
|
204
236
|
this.send("session.configure", settings);
|
|
205
237
|
}
|
|
206
238
|
/**
|
|
207
|
-
*
|
|
239
|
+
* Once a session is joined: send a text input message to the LLM. This will trigger a
|
|
208
240
|
* text response as well as an audio response if the session was opened with audio mode active.
|
|
209
241
|
*
|
|
210
242
|
* @remarks
|
|
@@ -221,7 +253,7 @@ var WebClient = class {
|
|
|
221
253
|
this.send("text.input.message", { text });
|
|
222
254
|
}
|
|
223
255
|
/**
|
|
224
|
-
*
|
|
256
|
+
* Once a session is joined: send a chunk of raw audio data to the LLM.
|
|
225
257
|
* Audio data chunks do not systematically & immediately trigger a model response:
|
|
226
258
|
* They get accumulated by the model to form a single input message, until:
|
|
227
259
|
* - commitAudioChunksSent is called, which flushes the accumulated audio and triggers a response
|
|
@@ -240,8 +272,8 @@ var WebClient = class {
|
|
|
240
272
|
this.send("audio.input.append", { audioData: chunk });
|
|
241
273
|
}
|
|
242
274
|
/**
|
|
243
|
-
*
|
|
244
|
-
* the last model response. This effectively flushes the audio buffer and triggers a
|
|
275
|
+
* Once a session is joined: triggers the processing of the accumulated audio data since
|
|
276
|
+
* the last model response. This effectively flushes the audio buffer and triggers a model response.
|
|
245
277
|
*
|
|
246
278
|
* @remarks
|
|
247
279
|
* With openai for example, this triggers (pseudo-code):
|
|
@@ -279,14 +311,22 @@ var WebClient = class {
|
|
|
279
311
|
ws.onopen = () => {
|
|
280
312
|
const eventSubs = audio ? [0 /* Text */, 1 /* Audio */] : [0 /* Text */];
|
|
281
313
|
ws.send(JSON.stringify({
|
|
282
|
-
type: "connection.
|
|
283
|
-
data: {
|
|
314
|
+
type: "connection.initiate",
|
|
315
|
+
data: {
|
|
316
|
+
subscription: eventSubs,
|
|
317
|
+
settings: {
|
|
318
|
+
audio: true,
|
|
319
|
+
voice: "alloy",
|
|
320
|
+
temperature: 0.8,
|
|
321
|
+
instructions: ""
|
|
322
|
+
}
|
|
323
|
+
}
|
|
284
324
|
}));
|
|
285
325
|
};
|
|
286
326
|
ws.onmessage = (event) => {
|
|
287
327
|
try {
|
|
288
328
|
const data = JSON.parse(event.data);
|
|
289
|
-
if (data.type === "connection.
|
|
329
|
+
if (data.type === "connection.initiated")
|
|
290
330
|
resolve(true);
|
|
291
331
|
else
|
|
292
332
|
reject(new Error(`Received unexpected event: ${data.type}`));
|
package/dist/index.d.cts
CHANGED
|
@@ -31,17 +31,13 @@ interface WebClientConfig {
|
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* System settings influencing the model behavior:
|
|
34
|
-
* @audio: to activate voice conversation
|
|
35
|
-
* @voice: depending on the LLM solution, this is the voice name to be used in audio
|
|
36
34
|
* @temperature: LLM creativity factor in 0-1 range
|
|
37
35
|
* @instructions: system instructions giving context, rules and directions to guide the LLM behavior
|
|
38
36
|
* @maxResponseToken: 1-4096 value, maximum number of token used for a single response. Undefined means unlimited.
|
|
39
37
|
*/
|
|
40
|
-
interface
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
temperature: number;
|
|
44
|
-
instructions: string;
|
|
38
|
+
interface SessionConfig {
|
|
39
|
+
temperature?: number;
|
|
40
|
+
instructions?: string;
|
|
45
41
|
maxResponseToken?: number;
|
|
46
42
|
}
|
|
47
43
|
/**
|
|
@@ -66,7 +62,7 @@ interface SessionSettings {
|
|
|
66
62
|
*/
|
|
67
63
|
interface EventHandlers {
|
|
68
64
|
onStreamClosed: (reason: string) => void;
|
|
69
|
-
onSessionConfigured?: (settings:
|
|
65
|
+
onSessionConfigured?: (settings: SessionConfig) => void;
|
|
70
66
|
onAudioResponseStart?: () => void;
|
|
71
67
|
onAudioResponseChunk?: (audioChunk: string) => void;
|
|
72
68
|
onAudioResponseEnd?: () => void;
|
|
@@ -74,6 +70,16 @@ interface EventHandlers {
|
|
|
74
70
|
onTranscriptResponse?: (transcript: string) => void;
|
|
75
71
|
onTechnicalError?: (error: string) => void;
|
|
76
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Description of an available tool that can be added to a session context.
|
|
75
|
+
* Tools included in the session context can be used by the AI model during the session.
|
|
76
|
+
* Tools (or functions) can be many things, for example a calendar manager, allowing
|
|
77
|
+
* the model to manage the user's schedule.
|
|
78
|
+
*/
|
|
79
|
+
interface ToolDescription {
|
|
80
|
+
name: string;
|
|
81
|
+
description: string;
|
|
82
|
+
}
|
|
77
83
|
/**
|
|
78
84
|
* This class is a code wrapper to integrate the Simfinity constellation server.
|
|
79
85
|
* The constellation server is a proxy managing streaming sessions with third party LLMs.
|
|
@@ -87,26 +93,37 @@ declare class WebClient {
|
|
|
87
93
|
private ws;
|
|
88
94
|
private sessionId;
|
|
89
95
|
constructor(config: WebClientConfig);
|
|
96
|
+
/**
|
|
97
|
+
* Retrieve the list of available tools:
|
|
98
|
+
* Tools, or functions, can be exposed to & added to the model's context, allowing it
|
|
99
|
+
* to use them during the session as part of its response creation process. In order to add
|
|
100
|
+
* a tool to the session context, it must be listed (by name) at session creation time
|
|
101
|
+
* (see startSession(...) function)
|
|
102
|
+
*
|
|
103
|
+
* @remarks
|
|
104
|
+
* Tools are remote functions exposed by MCP servers and integrated by the constellation server
|
|
105
|
+
*
|
|
106
|
+
* @exception
|
|
107
|
+
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
108
|
+
*/
|
|
109
|
+
fetchAvailableTools(): Promise<ToolDescription[]>;
|
|
90
110
|
/**
|
|
91
111
|
* Start a persistent chat room on the server, allowing for re-connection,
|
|
92
112
|
* when the streaming connection is lost. Once a session was started it must
|
|
93
113
|
* be closed to release the context on server side. See endSession().
|
|
94
114
|
*
|
|
95
115
|
* @remarks
|
|
96
|
-
* A session MUST exist to connect the stream.
|
|
116
|
+
* A session MUST exist first in order to connect the stream next.
|
|
97
117
|
*
|
|
98
|
-
* @param
|
|
99
|
-
* @param
|
|
118
|
+
* @param audioEnabled whether this session can receive & produce audio as well as text
|
|
119
|
+
* @param voiceName LLM specific voice name e.g. with OpenAI this could be 'alloy'
|
|
120
|
+
* @param tools a list of tool names to be included in this session. These must be matching the
|
|
121
|
+
* names returned by 'fetchAvailableTools()'.
|
|
100
122
|
*
|
|
101
123
|
* @exception
|
|
102
124
|
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```TypeScript
|
|
106
|
-
* await startSession("You are useful assistant", true)
|
|
107
|
-
* ```
|
|
108
125
|
*/
|
|
109
|
-
startSession(
|
|
126
|
+
startSession(audioEnabled: boolean, voiceName?: string, tools?: string[]): Promise<void>;
|
|
110
127
|
/**
|
|
111
128
|
* Close an opened, persistent chat room, effectively killing the streaming as well if still opened.
|
|
112
129
|
* If there is no active session, this method does nothing.
|
|
@@ -128,7 +145,7 @@ declare class WebClient {
|
|
|
128
145
|
* This method not only opens a websocket connection with the server but also initiates a
|
|
129
146
|
* handshake, where the server explicitly acknowledges and accepts the client connection.
|
|
130
147
|
*
|
|
131
|
-
* @param audio for
|
|
148
|
+
* @param audio for an audio-enabled session, request this streaming connection to include audio events
|
|
132
149
|
* @param handlers callback functions to handle every possible communication events coming from the server
|
|
133
150
|
*
|
|
134
151
|
* @exception
|
|
@@ -137,7 +154,7 @@ declare class WebClient {
|
|
|
137
154
|
* @example
|
|
138
155
|
* ```TypeScript
|
|
139
156
|
* // Open an audio connection: in this example we choose to handle only audio data, and ignore text.
|
|
140
|
-
* await
|
|
157
|
+
* await joinSession(true, {
|
|
141
158
|
* onStreamClosed: (reason: string) => { console.log("Stream connection lost"); },
|
|
142
159
|
* onAudioResponseStart: () => { console.log("The model is talking"); },
|
|
143
160
|
* onAudioResponseChunk: (audioChunk: string) => { audioPlayer.enqueue(audioChunk); },
|
|
@@ -147,7 +164,7 @@ declare class WebClient {
|
|
|
147
164
|
*/
|
|
148
165
|
joinSession(audio: boolean | undefined, handlers: EventHandlers): Promise<void>;
|
|
149
166
|
/**
|
|
150
|
-
*
|
|
167
|
+
* Once a session is joined: send a "system" update of the session settings.
|
|
151
168
|
* Allows to change some behavioral parameters like the temperature or system instructions.
|
|
152
169
|
* This does not trigger a model response.
|
|
153
170
|
*
|
|
@@ -155,14 +172,14 @@ declare class WebClient {
|
|
|
155
172
|
* With openai for example, this triggers (pseudo-code):
|
|
156
173
|
* webSocket.send({ type: "session.update", session: { ... }})
|
|
157
174
|
*
|
|
158
|
-
* @param settings
|
|
175
|
+
* @param settings new system settings to apply. Omitted values will remain unchanged
|
|
159
176
|
*
|
|
160
177
|
* @exception
|
|
161
178
|
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
162
179
|
*/
|
|
163
|
-
configureSession(settings:
|
|
180
|
+
configureSession(settings: SessionConfig): void;
|
|
164
181
|
/**
|
|
165
|
-
*
|
|
182
|
+
* Once a session is joined: send a text input message to the LLM. This will trigger a
|
|
166
183
|
* text response as well as an audio response if the session was opened with audio mode active.
|
|
167
184
|
*
|
|
168
185
|
* @remarks
|
|
@@ -177,7 +194,7 @@ declare class WebClient {
|
|
|
177
194
|
*/
|
|
178
195
|
sendText(text: string): void;
|
|
179
196
|
/**
|
|
180
|
-
*
|
|
197
|
+
* Once a session is joined: send a chunk of raw audio data to the LLM.
|
|
181
198
|
* Audio data chunks do not systematically & immediately trigger a model response:
|
|
182
199
|
* They get accumulated by the model to form a single input message, until:
|
|
183
200
|
* - commitAudioChunksSent is called, which flushes the accumulated audio and triggers a response
|
|
@@ -194,8 +211,8 @@ declare class WebClient {
|
|
|
194
211
|
*/
|
|
195
212
|
sendAudioChunk(chunk: string): void;
|
|
196
213
|
/**
|
|
197
|
-
*
|
|
198
|
-
* the last model response. This effectively flushes the audio buffer and triggers a
|
|
214
|
+
* Once a session is joined: triggers the processing of the accumulated audio data since
|
|
215
|
+
* the last model response. This effectively flushes the audio buffer and triggers a model response.
|
|
199
216
|
*
|
|
200
217
|
* @remarks
|
|
201
218
|
* With openai for example, this triggers (pseudo-code):
|
|
@@ -215,4 +232,4 @@ declare class WebClient {
|
|
|
215
232
|
private send;
|
|
216
233
|
}
|
|
217
234
|
|
|
218
|
-
export { type EventHandlers, type LlmType, type
|
|
235
|
+
export { type EventHandlers, type LlmType, type SessionConfig, type ToolDescription, WebClient, type WebClientConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -31,17 +31,13 @@ interface WebClientConfig {
|
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* System settings influencing the model behavior:
|
|
34
|
-
* @audio: to activate voice conversation
|
|
35
|
-
* @voice: depending on the LLM solution, this is the voice name to be used in audio
|
|
36
34
|
* @temperature: LLM creativity factor in 0-1 range
|
|
37
35
|
* @instructions: system instructions giving context, rules and directions to guide the LLM behavior
|
|
38
36
|
* @maxResponseToken: 1-4096 value, maximum number of token used for a single response. Undefined means unlimited.
|
|
39
37
|
*/
|
|
40
|
-
interface
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
temperature: number;
|
|
44
|
-
instructions: string;
|
|
38
|
+
interface SessionConfig {
|
|
39
|
+
temperature?: number;
|
|
40
|
+
instructions?: string;
|
|
45
41
|
maxResponseToken?: number;
|
|
46
42
|
}
|
|
47
43
|
/**
|
|
@@ -66,7 +62,7 @@ interface SessionSettings {
|
|
|
66
62
|
*/
|
|
67
63
|
interface EventHandlers {
|
|
68
64
|
onStreamClosed: (reason: string) => void;
|
|
69
|
-
onSessionConfigured?: (settings:
|
|
65
|
+
onSessionConfigured?: (settings: SessionConfig) => void;
|
|
70
66
|
onAudioResponseStart?: () => void;
|
|
71
67
|
onAudioResponseChunk?: (audioChunk: string) => void;
|
|
72
68
|
onAudioResponseEnd?: () => void;
|
|
@@ -74,6 +70,16 @@ interface EventHandlers {
|
|
|
74
70
|
onTranscriptResponse?: (transcript: string) => void;
|
|
75
71
|
onTechnicalError?: (error: string) => void;
|
|
76
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Description of an available tool that can be added to a session context.
|
|
75
|
+
* Tools included in the session context can be used by the AI model during the session.
|
|
76
|
+
* Tools (or functions) can be many things, for example a calendar manager, allowing
|
|
77
|
+
* the model to manage the user's schedule.
|
|
78
|
+
*/
|
|
79
|
+
interface ToolDescription {
|
|
80
|
+
name: string;
|
|
81
|
+
description: string;
|
|
82
|
+
}
|
|
77
83
|
/**
|
|
78
84
|
* This class is a code wrapper to integrate the Simfinity constellation server.
|
|
79
85
|
* The constellation server is a proxy managing streaming sessions with third party LLMs.
|
|
@@ -87,26 +93,37 @@ declare class WebClient {
|
|
|
87
93
|
private ws;
|
|
88
94
|
private sessionId;
|
|
89
95
|
constructor(config: WebClientConfig);
|
|
96
|
+
/**
|
|
97
|
+
* Retrieve the list of available tools:
|
|
98
|
+
* Tools, or functions, can be exposed to & added to the model's context, allowing it
|
|
99
|
+
* to use them during the session as part of its response creation process. In order to add
|
|
100
|
+
* a tool to the session context, it must be listed (by name) at session creation time
|
|
101
|
+
* (see startSession(...) function)
|
|
102
|
+
*
|
|
103
|
+
* @remarks
|
|
104
|
+
* Tools are remote functions exposed by MCP servers and integrated by the constellation server
|
|
105
|
+
*
|
|
106
|
+
* @exception
|
|
107
|
+
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
108
|
+
*/
|
|
109
|
+
fetchAvailableTools(): Promise<ToolDescription[]>;
|
|
90
110
|
/**
|
|
91
111
|
* Start a persistent chat room on the server, allowing for re-connection,
|
|
92
112
|
* when the streaming connection is lost. Once a session was started it must
|
|
93
113
|
* be closed to release the context on server side. See endSession().
|
|
94
114
|
*
|
|
95
115
|
* @remarks
|
|
96
|
-
* A session MUST exist to connect the stream.
|
|
116
|
+
* A session MUST exist first in order to connect the stream next.
|
|
97
117
|
*
|
|
98
|
-
* @param
|
|
99
|
-
* @param
|
|
118
|
+
* @param audioEnabled whether this session can receive & produce audio as well as text
|
|
119
|
+
* @param voiceName LLM specific voice name e.g. with OpenAI this could be 'alloy'
|
|
120
|
+
* @param tools a list of tool names to be included in this session. These must be matching the
|
|
121
|
+
* names returned by 'fetchAvailableTools()'.
|
|
100
122
|
*
|
|
101
123
|
* @exception
|
|
102
124
|
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```TypeScript
|
|
106
|
-
* await startSession("You are useful assistant", true)
|
|
107
|
-
* ```
|
|
108
125
|
*/
|
|
109
|
-
startSession(
|
|
126
|
+
startSession(audioEnabled: boolean, voiceName?: string, tools?: string[]): Promise<void>;
|
|
110
127
|
/**
|
|
111
128
|
* Close an opened, persistent chat room, effectively killing the streaming as well if still opened.
|
|
112
129
|
* If there is no active session, this method does nothing.
|
|
@@ -128,7 +145,7 @@ declare class WebClient {
|
|
|
128
145
|
* This method not only opens a websocket connection with the server but also initiates a
|
|
129
146
|
* handshake, where the server explicitly acknowledges and accepts the client connection.
|
|
130
147
|
*
|
|
131
|
-
* @param audio for
|
|
148
|
+
* @param audio for an audio-enabled session, request this streaming connection to include audio events
|
|
132
149
|
* @param handlers callback functions to handle every possible communication events coming from the server
|
|
133
150
|
*
|
|
134
151
|
* @exception
|
|
@@ -137,7 +154,7 @@ declare class WebClient {
|
|
|
137
154
|
* @example
|
|
138
155
|
* ```TypeScript
|
|
139
156
|
* // Open an audio connection: in this example we choose to handle only audio data, and ignore text.
|
|
140
|
-
* await
|
|
157
|
+
* await joinSession(true, {
|
|
141
158
|
* onStreamClosed: (reason: string) => { console.log("Stream connection lost"); },
|
|
142
159
|
* onAudioResponseStart: () => { console.log("The model is talking"); },
|
|
143
160
|
* onAudioResponseChunk: (audioChunk: string) => { audioPlayer.enqueue(audioChunk); },
|
|
@@ -147,7 +164,7 @@ declare class WebClient {
|
|
|
147
164
|
*/
|
|
148
165
|
joinSession(audio: boolean | undefined, handlers: EventHandlers): Promise<void>;
|
|
149
166
|
/**
|
|
150
|
-
*
|
|
167
|
+
* Once a session is joined: send a "system" update of the session settings.
|
|
151
168
|
* Allows to change some behavioral parameters like the temperature or system instructions.
|
|
152
169
|
* This does not trigger a model response.
|
|
153
170
|
*
|
|
@@ -155,14 +172,14 @@ declare class WebClient {
|
|
|
155
172
|
* With openai for example, this triggers (pseudo-code):
|
|
156
173
|
* webSocket.send({ type: "session.update", session: { ... }})
|
|
157
174
|
*
|
|
158
|
-
* @param settings
|
|
175
|
+
* @param settings new system settings to apply. Omitted values will remain unchanged
|
|
159
176
|
*
|
|
160
177
|
* @exception
|
|
161
178
|
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
162
179
|
*/
|
|
163
|
-
configureSession(settings:
|
|
180
|
+
configureSession(settings: SessionConfig): void;
|
|
164
181
|
/**
|
|
165
|
-
*
|
|
182
|
+
* Once a session is joined: send a text input message to the LLM. This will trigger a
|
|
166
183
|
* text response as well as an audio response if the session was opened with audio mode active.
|
|
167
184
|
*
|
|
168
185
|
* @remarks
|
|
@@ -177,7 +194,7 @@ declare class WebClient {
|
|
|
177
194
|
*/
|
|
178
195
|
sendText(text: string): void;
|
|
179
196
|
/**
|
|
180
|
-
*
|
|
197
|
+
* Once a session is joined: send a chunk of raw audio data to the LLM.
|
|
181
198
|
* Audio data chunks do not systematically & immediately trigger a model response:
|
|
182
199
|
* They get accumulated by the model to form a single input message, until:
|
|
183
200
|
* - commitAudioChunksSent is called, which flushes the accumulated audio and triggers a response
|
|
@@ -194,8 +211,8 @@ declare class WebClient {
|
|
|
194
211
|
*/
|
|
195
212
|
sendAudioChunk(chunk: string): void;
|
|
196
213
|
/**
|
|
197
|
-
*
|
|
198
|
-
* the last model response. This effectively flushes the audio buffer and triggers a
|
|
214
|
+
* Once a session is joined: triggers the processing of the accumulated audio data since
|
|
215
|
+
* the last model response. This effectively flushes the audio buffer and triggers a model response.
|
|
199
216
|
*
|
|
200
217
|
* @remarks
|
|
201
218
|
* With openai for example, this triggers (pseudo-code):
|
|
@@ -215,4 +232,4 @@ declare class WebClient {
|
|
|
215
232
|
private send;
|
|
216
233
|
}
|
|
217
234
|
|
|
218
|
-
export { type EventHandlers, type LlmType, type
|
|
235
|
+
export { type EventHandlers, type LlmType, type SessionConfig, type ToolDescription, WebClient, type WebClientConfig };
|
package/dist/index.js
CHANGED
|
@@ -5,26 +5,62 @@ var WebClient = class {
|
|
|
5
5
|
this.sessionId = null;
|
|
6
6
|
this.config = config;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Retrieve the list of available tools:
|
|
10
|
+
* Tools, or functions, can be exposed to & added to the model's context, allowing it
|
|
11
|
+
* to use them during the session as part of its response creation process. In order to add
|
|
12
|
+
* a tool to the session context, it must be listed (by name) at session creation time
|
|
13
|
+
* (see startSession(...) function)
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* Tools are remote functions exposed by MCP servers and integrated by the constellation server
|
|
17
|
+
*
|
|
18
|
+
* @exception
|
|
19
|
+
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
20
|
+
*/
|
|
21
|
+
async fetchAvailableTools() {
|
|
22
|
+
const response = await fetch(`${this.config.sessionEndpoint}/available_tools`, {
|
|
23
|
+
method: "GET",
|
|
24
|
+
headers: {
|
|
25
|
+
"Authorization": `Bearer ${this.config.key}`,
|
|
26
|
+
"Content-Type": "application/json",
|
|
27
|
+
"Accept": "application/json"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
throw new Error(`Could not fetch the list of available tools
|
|
32
|
+
[${response.status}:${response.statusText}]`);
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const result = await response.json();
|
|
36
|
+
return result != null ? result : [];
|
|
37
|
+
} catch (error) {
|
|
38
|
+
throw `Failed to read session create response: ${error}`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
8
41
|
/**
|
|
9
42
|
* Start a persistent chat room on the server, allowing for re-connection,
|
|
10
43
|
* when the streaming connection is lost. Once a session was started it must
|
|
11
44
|
* be closed to release the context on server side. See endSession().
|
|
12
45
|
*
|
|
13
46
|
* @remarks
|
|
14
|
-
* A session MUST exist to connect the stream.
|
|
47
|
+
* A session MUST exist first in order to connect the stream next.
|
|
15
48
|
*
|
|
16
|
-
* @param
|
|
17
|
-
* @param
|
|
49
|
+
* @param audioEnabled whether this session can receive & produce audio as well as text
|
|
50
|
+
* @param voiceName LLM specific voice name e.g. with OpenAI this could be 'alloy'
|
|
51
|
+
* @param tools a list of tool names to be included in this session. These must be matching the
|
|
52
|
+
* names returned by 'fetchAvailableTools()'.
|
|
18
53
|
*
|
|
19
54
|
* @exception
|
|
20
55
|
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```TypeScript
|
|
24
|
-
* await startSession("You are useful assistant", true)
|
|
25
|
-
* ```
|
|
26
56
|
*/
|
|
27
|
-
async startSession(
|
|
57
|
+
async startSession(audioEnabled, voiceName, tools = []) {
|
|
58
|
+
const prepareBody = {
|
|
59
|
+
llmProvider: this.config.llm,
|
|
60
|
+
audioEnabled,
|
|
61
|
+
voiceName,
|
|
62
|
+
includeTools: tools
|
|
63
|
+
};
|
|
28
64
|
const response = await fetch(`${this.config.sessionEndpoint}/prepare_session`, {
|
|
29
65
|
method: "POST",
|
|
30
66
|
headers: {
|
|
@@ -32,11 +68,7 @@ var WebClient = class {
|
|
|
32
68
|
"Content-Type": "application/json",
|
|
33
69
|
"Accept": "application/json"
|
|
34
70
|
},
|
|
35
|
-
body: JSON.stringify(
|
|
36
|
-
llmProvider: this.config.llm,
|
|
37
|
-
systemPrompt: instructions,
|
|
38
|
-
audio
|
|
39
|
-
})
|
|
71
|
+
body: JSON.stringify(prepareBody)
|
|
40
72
|
});
|
|
41
73
|
if (!response.ok) {
|
|
42
74
|
throw new Error(`Could not create a new chat session
|
|
@@ -90,7 +122,7 @@ var WebClient = class {
|
|
|
90
122
|
* This method not only opens a websocket connection with the server but also initiates a
|
|
91
123
|
* handshake, where the server explicitly acknowledges and accepts the client connection.
|
|
92
124
|
*
|
|
93
|
-
* @param audio for
|
|
125
|
+
* @param audio for an audio-enabled session, request this streaming connection to include audio events
|
|
94
126
|
* @param handlers callback functions to handle every possible communication events coming from the server
|
|
95
127
|
*
|
|
96
128
|
* @exception
|
|
@@ -99,7 +131,7 @@ var WebClient = class {
|
|
|
99
131
|
* @example
|
|
100
132
|
* ```TypeScript
|
|
101
133
|
* // Open an audio connection: in this example we choose to handle only audio data, and ignore text.
|
|
102
|
-
* await
|
|
134
|
+
* await joinSession(true, {
|
|
103
135
|
* onStreamClosed: (reason: string) => { console.log("Stream connection lost"); },
|
|
104
136
|
* onAudioResponseStart: () => { console.log("The model is talking"); },
|
|
105
137
|
* onAudioResponseChunk: (audioChunk: string) => { audioPlayer.enqueue(audioChunk); },
|
|
@@ -161,7 +193,7 @@ var WebClient = class {
|
|
|
161
193
|
this.ws = ws;
|
|
162
194
|
}
|
|
163
195
|
/**
|
|
164
|
-
*
|
|
196
|
+
* Once a session is joined: send a "system" update of the session settings.
|
|
165
197
|
* Allows to change some behavioral parameters like the temperature or system instructions.
|
|
166
198
|
* This does not trigger a model response.
|
|
167
199
|
*
|
|
@@ -169,16 +201,16 @@ var WebClient = class {
|
|
|
169
201
|
* With openai for example, this triggers (pseudo-code):
|
|
170
202
|
* webSocket.send({ type: "session.update", session: { ... }})
|
|
171
203
|
*
|
|
172
|
-
* @param settings
|
|
204
|
+
* @param settings new system settings to apply. Omitted values will remain unchanged
|
|
173
205
|
*
|
|
174
206
|
* @exception
|
|
175
207
|
* This method throws new Error(...) if unable to execute successfully for any reason.
|
|
176
208
|
*/
|
|
177
|
-
|
|
209
|
+
configureSession(settings) {
|
|
178
210
|
this.send("session.configure", settings);
|
|
179
211
|
}
|
|
180
212
|
/**
|
|
181
|
-
*
|
|
213
|
+
* Once a session is joined: send a text input message to the LLM. This will trigger a
|
|
182
214
|
* text response as well as an audio response if the session was opened with audio mode active.
|
|
183
215
|
*
|
|
184
216
|
* @remarks
|
|
@@ -195,7 +227,7 @@ var WebClient = class {
|
|
|
195
227
|
this.send("text.input.message", { text });
|
|
196
228
|
}
|
|
197
229
|
/**
|
|
198
|
-
*
|
|
230
|
+
* Once a session is joined: send a chunk of raw audio data to the LLM.
|
|
199
231
|
* Audio data chunks do not systematically & immediately trigger a model response:
|
|
200
232
|
* They get accumulated by the model to form a single input message, until:
|
|
201
233
|
* - commitAudioChunksSent is called, which flushes the accumulated audio and triggers a response
|
|
@@ -214,8 +246,8 @@ var WebClient = class {
|
|
|
214
246
|
this.send("audio.input.append", { audioData: chunk });
|
|
215
247
|
}
|
|
216
248
|
/**
|
|
217
|
-
*
|
|
218
|
-
* the last model response. This effectively flushes the audio buffer and triggers a
|
|
249
|
+
* Once a session is joined: triggers the processing of the accumulated audio data since
|
|
250
|
+
* the last model response. This effectively flushes the audio buffer and triggers a model response.
|
|
219
251
|
*
|
|
220
252
|
* @remarks
|
|
221
253
|
* With openai for example, this triggers (pseudo-code):
|
|
@@ -253,14 +285,22 @@ var WebClient = class {
|
|
|
253
285
|
ws.onopen = () => {
|
|
254
286
|
const eventSubs = audio ? [0 /* Text */, 1 /* Audio */] : [0 /* Text */];
|
|
255
287
|
ws.send(JSON.stringify({
|
|
256
|
-
type: "connection.
|
|
257
|
-
data: {
|
|
288
|
+
type: "connection.initiate",
|
|
289
|
+
data: {
|
|
290
|
+
subscription: eventSubs,
|
|
291
|
+
settings: {
|
|
292
|
+
audio: true,
|
|
293
|
+
voice: "alloy",
|
|
294
|
+
temperature: 0.8,
|
|
295
|
+
instructions: ""
|
|
296
|
+
}
|
|
297
|
+
}
|
|
258
298
|
}));
|
|
259
299
|
};
|
|
260
300
|
ws.onmessage = (event) => {
|
|
261
301
|
try {
|
|
262
302
|
const data = JSON.parse(event.data);
|
|
263
|
-
if (data.type === "connection.
|
|
303
|
+
if (data.type === "connection.initiated")
|
|
264
304
|
resolve(true);
|
|
265
305
|
else
|
|
266
306
|
reject(new Error(`Received unexpected event: ${data.type}`));
|