@kivox/client 0.1.0-beta.2 → 0.1.0-beta.21
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 +4 -4
- package/dist/index.d.ts +217 -234
- package/dist/index.js +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Kivox JavaScript client
|
|
2
2
|
|
|
3
|
-
`@kivox/client` is the official JavaScript/TypeScript client for interacting with
|
|
3
|
+
`@kivox/client` is the official JavaScript/TypeScript client for interacting with Kivox. It provides the necessary abstractions and bindings to handle sessions, real-time events, audio, and communication with agents.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
## Documentation
|
|
15
15
|
|
|
16
|
-
<https://kivox.
|
|
16
|
+
<https://docs.kivox.com.co/packages/kivox-client>
|
|
17
17
|
|
|
18
18
|
## Installation
|
|
19
19
|
|
|
@@ -84,7 +84,7 @@ const kivox = new KivoxClient({
|
|
|
84
84
|
|
|
85
85
|
## Contributing
|
|
86
86
|
|
|
87
|
-
[
|
|
87
|
+
[CONTRIBUTING.md](https://github.com/ekisa-team/kivox/blob/main/CONTRIBUTING.md)
|
|
88
88
|
|
|
89
89
|
## License
|
|
90
90
|
|
package/dist/index.d.ts
CHANGED
|
@@ -68,50 +68,34 @@ type Agent = {
|
|
|
68
68
|
id: string
|
|
69
69
|
template_id: string
|
|
70
70
|
config: AgentConfig
|
|
71
|
-
|
|
71
|
+
secrets: AgentSecret[]
|
|
72
|
+
ork_source: string
|
|
72
73
|
status: AgentStatus
|
|
73
74
|
created_at: Date
|
|
74
75
|
updated_at: Date
|
|
75
76
|
};
|
|
76
77
|
type AgentConfig = {
|
|
78
|
+
avatar_url?: string
|
|
77
79
|
name: string
|
|
80
|
+
description?: string
|
|
81
|
+
language?: string
|
|
82
|
+
global_system_prompt?: string
|
|
83
|
+
max_session_duration_minutes?: number
|
|
84
|
+
max_silence_timeout_seconds?: number
|
|
85
|
+
allow_interruptions?: boolean
|
|
86
|
+
llm_engine?: string
|
|
87
|
+
llm_model?: string
|
|
88
|
+
};
|
|
89
|
+
type AgentSecret = {
|
|
90
|
+
key: string
|
|
91
|
+
value: string
|
|
78
92
|
description: string
|
|
79
|
-
system_prompt: string
|
|
80
|
-
language: string
|
|
81
|
-
max_session_duration_minutes: number
|
|
82
|
-
max_silence_timeout_seconds: number
|
|
83
|
-
allow_interruptions: boolean
|
|
84
|
-
};
|
|
85
|
-
type AgentBlueprint<
|
|
86
|
-
NodeType = unknown,
|
|
87
|
-
EdgeType = unknown
|
|
88
|
-
> = {
|
|
89
|
-
nodes: NodeType[]
|
|
90
|
-
edges: EdgeType[]
|
|
91
|
-
};
|
|
92
|
-
type AgentCreate = Partial<Pick<Agent, "config" | "blueprint" | "status" | "template_id">>;
|
|
93
|
-
type AgentUpdate = Partial<Pick<AgentCreate, "config" | "blueprint">>;
|
|
94
|
-
type NodeType = "CONTROL.START" | "CONTROL.DIALOG" | "CONTROL.END" | "LOGICAL.EVAL" | "FUNCTION.SET_VAR" | "FUNCTION.WEBHOOK" | "FUNCTION.EMAIL_NOTIFY" | "FUNCTION.KIBOT_NOTIFY" | "FUNCTION.TRANSFER" | "FUNCTION.TERMINATE";
|
|
95
|
-
type Node = {
|
|
96
|
-
id: string
|
|
97
|
-
type: NodeType
|
|
98
|
-
position: NodePosition
|
|
99
|
-
measured: NodeDimensions
|
|
100
|
-
data: Record<string, unknown>
|
|
101
|
-
};
|
|
102
|
-
type NodePosition = {
|
|
103
|
-
x: number
|
|
104
|
-
y: number
|
|
105
93
|
};
|
|
106
|
-
type
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
id: string
|
|
112
|
-
source: string
|
|
113
|
-
target: string
|
|
114
|
-
label: string
|
|
94
|
+
type AgentCreate = Partial<Pick<Agent, "config" | "secrets" | "ork_source" | "status" | "template_id">>;
|
|
95
|
+
type AgentUpdate = Partial<Pick<AgentCreate, "config" | "secrets" | "ork_source">>;
|
|
96
|
+
type AgentCompilationDiagnostic = {
|
|
97
|
+
errors: string[]
|
|
98
|
+
warnings: string[]
|
|
115
99
|
};
|
|
116
100
|
/**
|
|
117
101
|
* Configuration for listing agents.
|
|
@@ -125,7 +109,7 @@ type AgentListParams = {
|
|
|
125
109
|
search?: string
|
|
126
110
|
};
|
|
127
111
|
/**
|
|
128
|
-
* Client for interacting with
|
|
112
|
+
* Client for interacting with Kivox agents.
|
|
129
113
|
*
|
|
130
114
|
* @example
|
|
131
115
|
* ```ts
|
|
@@ -214,6 +198,14 @@ declare class AgentClient {
|
|
|
214
198
|
*/
|
|
215
199
|
delete(id: string): Promise<Agent>;
|
|
216
200
|
/**
|
|
201
|
+
* Compiles the Ork source code of an agent.
|
|
202
|
+
*
|
|
203
|
+
* @param id Agent ID
|
|
204
|
+
* @param orkSource Updated Ork source code. If not provided, the current Ork source code is used.
|
|
205
|
+
* @returns Compiled agent
|
|
206
|
+
*/
|
|
207
|
+
compile(id: string, orkSource?: string): Promise<AgentCompilationDiagnostic>;
|
|
208
|
+
/**
|
|
217
209
|
* Parses a list of agents with stringified config and blueprint fields.
|
|
218
210
|
*
|
|
219
211
|
* @returns List of parsed agents.
|
|
@@ -251,197 +243,157 @@ declare class WebSocketTransport {
|
|
|
251
243
|
connect(path: string): WebSocket;
|
|
252
244
|
}
|
|
253
245
|
/**
|
|
254
|
-
*
|
|
246
|
+
* Initializes a new conversational session.
|
|
247
|
+
* It must be the first message sent after connection establishment.
|
|
255
248
|
*/
|
|
256
|
-
type
|
|
257
|
-
type: "
|
|
249
|
+
type ClientHandshake = {
|
|
250
|
+
type: "handshake"
|
|
258
251
|
agent_id: string
|
|
259
252
|
};
|
|
260
253
|
/**
|
|
261
|
-
*
|
|
262
|
-
*/
|
|
263
|
-
type ClientSessionEnd = {
|
|
264
|
-
type: "session.end"
|
|
265
|
-
conversation_id: string
|
|
266
|
-
};
|
|
267
|
-
/**
|
|
268
|
-
* Sends a text input from the client to the server.
|
|
254
|
+
* Carries a single user text message.
|
|
269
255
|
*/
|
|
270
256
|
type ClientInputText = {
|
|
271
|
-
type: "
|
|
272
|
-
conversation_id: string
|
|
257
|
+
type: "input_text"
|
|
273
258
|
text: string
|
|
274
259
|
};
|
|
275
260
|
/**
|
|
276
|
-
*
|
|
261
|
+
* Signals that audio input will begin.
|
|
262
|
+
* Typically followed by one or more binary WebSocket frames.
|
|
277
263
|
*/
|
|
278
264
|
type ClientInputAudio = {
|
|
279
|
-
type: "
|
|
280
|
-
conversation_id: string
|
|
265
|
+
type: "input_audio"
|
|
281
266
|
};
|
|
282
267
|
/**
|
|
283
|
-
*
|
|
268
|
+
* Signals that a streamed audio chunk will follow in the next binary frame.
|
|
284
269
|
*/
|
|
285
270
|
type ClientInputAudioStream = {
|
|
286
|
-
type: "
|
|
287
|
-
conversation_id: string
|
|
271
|
+
type: "input_audio_stream"
|
|
288
272
|
};
|
|
289
273
|
/**
|
|
290
|
-
*
|
|
274
|
+
* Requests interruption of the current streaming response.
|
|
291
275
|
*/
|
|
292
|
-
type
|
|
293
|
-
type: "
|
|
294
|
-
conversation_id: string
|
|
276
|
+
type ClientCancel = {
|
|
277
|
+
type: "cancel"
|
|
295
278
|
};
|
|
296
279
|
/**
|
|
297
|
-
*
|
|
280
|
+
* Requests graceful session termination.
|
|
298
281
|
*/
|
|
299
|
-
type
|
|
300
|
-
|
|
301
|
-
* Sent by the server when a handshake offer is accepted.
|
|
302
|
-
*/
|
|
303
|
-
type ServerSessionHandshakeAccept = {
|
|
304
|
-
type: "session.handshake.accept"
|
|
305
|
-
agent_id: string
|
|
306
|
-
conversation_id: string
|
|
307
|
-
};
|
|
308
|
-
/**
|
|
309
|
-
* Sent by the server when a handshake offer is rejected.
|
|
310
|
-
*/
|
|
311
|
-
type ServerSessionHandshakeReject = {
|
|
312
|
-
type: "session.handshake.reject"
|
|
313
|
-
reason: string
|
|
282
|
+
type ClientEndSession = {
|
|
283
|
+
type: "end"
|
|
314
284
|
};
|
|
315
285
|
/**
|
|
316
|
-
*
|
|
286
|
+
* Union type for all JSON messages sent from the client to the server.
|
|
317
287
|
*/
|
|
318
|
-
type
|
|
319
|
-
type: "session.start"
|
|
320
|
-
conversation_id: string
|
|
321
|
-
start_time: number
|
|
322
|
-
end_time: number
|
|
323
|
-
max_duration_ms: number
|
|
324
|
-
};
|
|
288
|
+
type ClientMessage = ClientHandshake | ClientInputText | ClientInputAudio | ClientInputAudioStream | ClientCancel | ClientEndSession;
|
|
325
289
|
/**
|
|
326
|
-
*
|
|
290
|
+
* Confirms successful session initialization.
|
|
327
291
|
*/
|
|
328
|
-
type
|
|
329
|
-
type: "
|
|
292
|
+
type ServerHandshakeOK = {
|
|
293
|
+
type: "handshake_ok"
|
|
330
294
|
conversation_id: string
|
|
331
295
|
};
|
|
332
296
|
/**
|
|
333
|
-
*
|
|
297
|
+
* Indicates that the session could not be created.
|
|
334
298
|
*/
|
|
335
|
-
type
|
|
336
|
-
type: "
|
|
337
|
-
|
|
338
|
-
max_duration_ms: number
|
|
339
|
-
remaining_time_ms: number
|
|
340
|
-
elapsed_time_ms: number
|
|
341
|
-
};
|
|
342
|
-
/**
|
|
343
|
-
* Sent when a session ends due to inactivity or exceeding max duration.
|
|
344
|
-
*/
|
|
345
|
-
type ServerSessionTimeout = {
|
|
346
|
-
type: "session.timeout"
|
|
347
|
-
conversation_id: string
|
|
348
|
-
};
|
|
349
|
-
/**
|
|
350
|
-
* Signals that the server has detected the start of speech.
|
|
351
|
-
*/
|
|
352
|
-
type ServerSpeechStart = {
|
|
353
|
-
type: "speech.start"
|
|
354
|
-
conversation_id: string
|
|
299
|
+
type ServerHandshakeError = {
|
|
300
|
+
type: "handshake_error"
|
|
301
|
+
reason: string
|
|
355
302
|
};
|
|
356
303
|
/**
|
|
357
|
-
*
|
|
304
|
+
* Carries a full text message generated by the runtime.
|
|
358
305
|
*/
|
|
359
|
-
type
|
|
360
|
-
type: "
|
|
361
|
-
|
|
306
|
+
type ServerTextFull = {
|
|
307
|
+
type: "text_full"
|
|
308
|
+
content: string
|
|
362
309
|
};
|
|
363
310
|
/**
|
|
364
|
-
*
|
|
311
|
+
* Carries a streamed text fragment generated by the runtime.
|
|
365
312
|
*/
|
|
366
|
-
type
|
|
367
|
-
type: "
|
|
368
|
-
conversation_id: string
|
|
313
|
+
type ServerTextDelta = {
|
|
314
|
+
type: "text_delta"
|
|
369
315
|
chunk: string
|
|
370
316
|
};
|
|
371
317
|
/**
|
|
372
|
-
*
|
|
318
|
+
* Carries metadata for a streamed audio fragment generated by the runtime.
|
|
319
|
+
* The actual binary audio data is delivered in the immediately following binary frame
|
|
320
|
+
* and merged into this object by the transport layer.
|
|
373
321
|
*/
|
|
374
|
-
type
|
|
375
|
-
type: "
|
|
376
|
-
|
|
322
|
+
type ServerAudioDelta = {
|
|
323
|
+
type: "audio_delta"
|
|
324
|
+
/** Expected size of the incoming binary payload in bytes */
|
|
377
325
|
size: number
|
|
326
|
+
/** The binary audio data attached dynamically by the transport layer */
|
|
378
327
|
audio: Blob
|
|
379
328
|
};
|
|
380
329
|
/**
|
|
381
|
-
* Signals that the
|
|
330
|
+
* Signals that the runtime has completed its turn and is awaiting further user input.
|
|
382
331
|
*/
|
|
383
|
-
type
|
|
384
|
-
type: "
|
|
385
|
-
conversation_id: string
|
|
332
|
+
type ServerTurnComplete = {
|
|
333
|
+
type: "turn_complete"
|
|
386
334
|
};
|
|
387
335
|
/**
|
|
388
|
-
*
|
|
336
|
+
* Signals that the conversation flow reached its exit node.
|
|
337
|
+
* The session will close shortly after this event.
|
|
389
338
|
*/
|
|
390
|
-
type
|
|
391
|
-
type: "
|
|
392
|
-
conversation_id: string
|
|
339
|
+
type ServerFlowComplete = {
|
|
340
|
+
type: "flow_complete"
|
|
393
341
|
};
|
|
394
342
|
/**
|
|
395
|
-
*
|
|
343
|
+
* Represents a non-fatal execution or protocol error.
|
|
344
|
+
* The session remains active unless followed by a SessionClosed event.
|
|
396
345
|
*/
|
|
397
|
-
type
|
|
398
|
-
type: "
|
|
399
|
-
conversation_id: string
|
|
346
|
+
type ServerError = {
|
|
347
|
+
type: "error"
|
|
400
348
|
code: string
|
|
401
349
|
message: string
|
|
402
350
|
};
|
|
403
351
|
/**
|
|
404
|
-
*
|
|
352
|
+
* Provides periodic timing information for the active session.
|
|
405
353
|
*/
|
|
406
|
-
type
|
|
354
|
+
type ServerTick = {
|
|
355
|
+
type: "tick"
|
|
356
|
+
/** Milliseconds until the session times out */
|
|
357
|
+
remaining_ms: number
|
|
358
|
+
/** Milliseconds elapsed since the session started */
|
|
359
|
+
elapsed_ms: number
|
|
360
|
+
};
|
|
407
361
|
/**
|
|
408
|
-
*
|
|
362
|
+
* Indicates that the session is closing.
|
|
409
363
|
*/
|
|
410
|
-
type
|
|
364
|
+
type ServerSessionClosed = {
|
|
365
|
+
type: "session_closed"
|
|
366
|
+
reason: string
|
|
367
|
+
};
|
|
411
368
|
/**
|
|
412
|
-
* Union type for all messages sent from the server to the client
|
|
369
|
+
* Union type for all messages sent from the server to the client.
|
|
413
370
|
*/
|
|
414
|
-
type
|
|
371
|
+
type ServerMessage = ServerHandshakeOK | ServerHandshakeError | ServerTextFull | ServerTextDelta | ServerAudioDelta | ServerTurnComplete | ServerFlowComplete | ServerError | ServerTick | ServerSessionClosed;
|
|
415
372
|
/**
|
|
416
|
-
*
|
|
373
|
+
* Messages related to the initial connection phase.
|
|
417
374
|
*/
|
|
418
|
-
type
|
|
375
|
+
type ServerConnectionMessage = ServerHandshakeOK | ServerHandshakeError;
|
|
419
376
|
/**
|
|
420
|
-
* Synthetic event emitted when the connection to the server
|
|
377
|
+
* Synthetic event emitted when the WebSocket connection to the server drops unexpectedly.
|
|
421
378
|
*/
|
|
422
379
|
type SessionConnectionLostEvent = {
|
|
423
|
-
type: "
|
|
424
|
-
conversation_id: string
|
|
380
|
+
type: "connection_lost"
|
|
425
381
|
reason: "socket_closed" | "socket_error"
|
|
426
382
|
};
|
|
427
383
|
/**
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
* @remarks
|
|
431
|
-
* Connection messages are handled internally during connection establishment
|
|
432
|
-
* and are not exposed through the session's `onEvent` callback.
|
|
384
|
+
* Union type of all events that can be emitted during an active conversation session.
|
|
433
385
|
*/
|
|
434
|
-
type ServerSessionEvent =
|
|
386
|
+
type ServerSessionEvent = ServerTextFull | ServerTextDelta | ServerAudioDelta | ServerTurnComplete | ServerFlowComplete | ServerError | ServerTick | ServerSessionClosed | SessionConnectionLostEvent;
|
|
435
387
|
/**
|
|
436
|
-
* Error thrown by the transport layer.
|
|
388
|
+
* Error thrown by the transport layer when connection or state issues occur.
|
|
437
389
|
*/
|
|
438
390
|
declare class ConversationTransportError extends Error {
|
|
439
391
|
readonly code: string;
|
|
440
392
|
constructor(message: string, code?: string);
|
|
441
393
|
}
|
|
442
394
|
/**
|
|
443
|
-
* Low-level WebSocket transport for conversation protocol.
|
|
444
|
-
* Handles connection lifecycle and
|
|
395
|
+
* Low-level WebSocket transport for the conversation protocol.
|
|
396
|
+
* Handles connection lifecycle and distinct routing for JSON and binary messages.
|
|
445
397
|
*/
|
|
446
398
|
declare class ConversationTransport {
|
|
447
399
|
private;
|
|
@@ -451,108 +403,139 @@ declare class ConversationTransport {
|
|
|
451
403
|
private _onBinary;
|
|
452
404
|
private _onError;
|
|
453
405
|
private _onClose;
|
|
406
|
+
/**
|
|
407
|
+
* Creates a new ConversationTransport.
|
|
408
|
+
* @param _ws The underlying WebSocket instance to wrap.
|
|
409
|
+
*/
|
|
454
410
|
constructor(_ws: WebSocket);
|
|
455
411
|
/**
|
|
456
|
-
* Waits for WebSocket to open.
|
|
457
|
-
* @throws {ConversationTransportError} If already connected or
|
|
412
|
+
* Waits for the WebSocket connection to fully open.
|
|
413
|
+
* @throws {ConversationTransportError} If the socket is already connected, closing, or fails to connect.
|
|
458
414
|
*/
|
|
459
415
|
connect(): Promise<void>;
|
|
460
416
|
/**
|
|
461
|
-
* Sends a JSON message to the server.
|
|
462
|
-
* @
|
|
417
|
+
* Sends a structured JSON message to the server.
|
|
418
|
+
* @param message The client message to send.
|
|
419
|
+
* @throws {ConversationTransportError} If the WebSocket is not currently open.
|
|
463
420
|
*/
|
|
464
421
|
send(message: ClientMessage): void;
|
|
465
422
|
/**
|
|
466
|
-
* Sends binary data (audio) to the server.
|
|
467
|
-
* @
|
|
423
|
+
* Sends binary data (like raw audio) to the server via a pure binary WebSocket frame.
|
|
424
|
+
* @param data The Blob representing the binary data.
|
|
425
|
+
* @throws {ConversationTransportError} If the WebSocket is not currently open.
|
|
468
426
|
*/
|
|
469
427
|
sendBinary(data: Blob): Promise<void>;
|
|
470
428
|
/**
|
|
471
|
-
* Registers a callback
|
|
429
|
+
* Registers a callback to be invoked when a JSON message is received from the server.
|
|
430
|
+
* @param handler The callback function.
|
|
472
431
|
*/
|
|
473
432
|
onMessage(handler: (msg: ServerMessage) => void): void;
|
|
474
433
|
/**
|
|
475
|
-
* Registers a callback
|
|
434
|
+
* Registers a callback to be invoked when a pure binary frame is received from the server.
|
|
435
|
+
* @param handler The callback function.
|
|
476
436
|
*/
|
|
477
437
|
onBinary(handler: (blob: Blob) => void): void;
|
|
478
438
|
/**
|
|
479
|
-
* Registers a callback
|
|
439
|
+
* Registers a callback to be invoked if a WebSocket error occurs.
|
|
440
|
+
* @param handler The callback function.
|
|
480
441
|
*/
|
|
481
442
|
onError(handler: (error: Error) => void): void;
|
|
482
443
|
/**
|
|
483
|
-
* Registers a callback
|
|
444
|
+
* Registers a callback to be invoked when the WebSocket connection is closed.
|
|
445
|
+
* @param handler The callback function.
|
|
484
446
|
*/
|
|
485
447
|
onClose(handler: () => void): void;
|
|
486
448
|
/**
|
|
487
|
-
* Closes the WebSocket connection and cleans up resources.
|
|
449
|
+
* Closes the underlying WebSocket connection and cleans up resources.
|
|
488
450
|
*/
|
|
489
451
|
close(): void;
|
|
490
452
|
}
|
|
491
453
|
/**
|
|
492
|
-
* Configuration
|
|
454
|
+
* Configuration options provided when establishing a conversation session.
|
|
493
455
|
*/
|
|
494
456
|
type ConversationSessionConfig = {
|
|
495
457
|
/**
|
|
496
|
-
*
|
|
458
|
+
* A callback function invoked whenever an event is emitted by the server during the session.
|
|
497
459
|
*
|
|
498
460
|
* @remarks
|
|
499
|
-
*
|
|
461
|
+
* For `audio_delta` events, the SDK automatically waits for the subsequent binary WebSocket frame
|
|
462
|
+
* and attaches the resulting `Blob` to the event object before triggering this callback.
|
|
500
463
|
*/
|
|
501
464
|
onEvent?: (event: ServerSessionEvent) => void
|
|
502
465
|
};
|
|
503
466
|
/**
|
|
504
|
-
* Represents an active conversation session with a
|
|
505
|
-
* Provides methods to
|
|
467
|
+
* Represents an active, real-time conversation session with a Kivox agent.
|
|
468
|
+
* Provides methods to dispatch user inputs and lifecycle commands, as well as tracking basic session state.
|
|
506
469
|
*/
|
|
507
470
|
declare class ConversationSession {
|
|
508
471
|
private;
|
|
509
472
|
private _transport;
|
|
510
473
|
private _conversationId;
|
|
511
|
-
private _maxDurationMs;
|
|
512
|
-
private _startTime;
|
|
513
|
-
private _endTime;
|
|
514
474
|
private _closed;
|
|
515
|
-
private _pendingAudioMetadata;
|
|
516
475
|
private _onEvent;
|
|
517
|
-
|
|
476
|
+
private _pendingAudioMetadata;
|
|
477
|
+
private _remainingMs;
|
|
478
|
+
private _elapsedMs;
|
|
479
|
+
/**
|
|
480
|
+
* The unique server-generated ID for this active conversation.
|
|
481
|
+
*/
|
|
518
482
|
get conversationId(): string;
|
|
519
|
-
/**
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
483
|
+
/**
|
|
484
|
+
* The number of milliseconds remaining until the engine enforces a session timeout.
|
|
485
|
+
* This value is periodically synced via server 'tick' events.
|
|
486
|
+
*/
|
|
487
|
+
get remainingMs(): number;
|
|
488
|
+
/**
|
|
489
|
+
* The number of milliseconds elapsed since the session was initiated.
|
|
490
|
+
* This value is periodically synced via server 'tick' events.
|
|
491
|
+
*/
|
|
492
|
+
get elapsedMs(): number;
|
|
493
|
+
/**
|
|
494
|
+
* Indicates whether the session has been permanently closed.
|
|
495
|
+
*/
|
|
526
496
|
get closed(): boolean;
|
|
527
|
-
constructor(transport: ConversationTransport, conversationId: string, maxDurationMs: number, startTime: number, endTime: number, config: ConversationSessionConfig);
|
|
528
497
|
/**
|
|
529
|
-
*
|
|
530
|
-
*
|
|
498
|
+
* Constructs a new active ConversationSession.
|
|
499
|
+
* Normally called internally by `ConversationClient.connect()`.
|
|
500
|
+
*
|
|
501
|
+
* @param transport The underlying active WebSocket transport.
|
|
502
|
+
* @param conversationId The ID assigned by the server during the handshake.
|
|
503
|
+
* @param config User-provided configuration options (e.g., event handlers).
|
|
504
|
+
*/
|
|
505
|
+
constructor(transport: ConversationTransport, conversationId: string, config: ConversationSessionConfig);
|
|
506
|
+
/**
|
|
507
|
+
* Sends a single textual user input to the agent.
|
|
508
|
+
*
|
|
509
|
+
* @param text The textual payload provided by the user.
|
|
531
510
|
*/
|
|
532
511
|
sendText(text: string): void;
|
|
533
512
|
/**
|
|
534
|
-
* Sends a complete audio
|
|
535
|
-
*
|
|
513
|
+
* Sends a complete, recorded audio buffer to the agent.
|
|
514
|
+
* First sends an `input_audio` header, then dispatches the binary frame.
|
|
515
|
+
*
|
|
516
|
+
* @param audio The raw binary audio file/buffer.
|
|
536
517
|
*/
|
|
537
518
|
sendAudio(audio: Blob): void;
|
|
538
519
|
/**
|
|
539
|
-
* Streams
|
|
540
|
-
*
|
|
520
|
+
* Streams a fragment of real-time audio to the agent.
|
|
521
|
+
* First sends an `input_audio_stream` header, then dispatches the binary frame.
|
|
522
|
+
*
|
|
523
|
+
* @param chunk The raw binary audio fragment.
|
|
541
524
|
*/
|
|
542
525
|
streamAudio(chunk: Blob): void;
|
|
543
526
|
/**
|
|
544
|
-
* Requests the
|
|
545
|
-
* The
|
|
527
|
+
* Requests that the server immediately halt the currently streaming assistant response.
|
|
528
|
+
* The session remains open and the agent will await the next user input.
|
|
546
529
|
*/
|
|
547
530
|
cancelRequest(): void;
|
|
548
531
|
/**
|
|
549
|
-
*
|
|
550
|
-
*
|
|
532
|
+
* Instructs the server to gracefully terminate the conversation.
|
|
533
|
+
* Wait for the resulting `session_closed` event to confirm termination.
|
|
551
534
|
*/
|
|
552
535
|
end(): void;
|
|
553
536
|
/**
|
|
554
|
-
* Immediately
|
|
555
|
-
*
|
|
537
|
+
* Immediately tears down the underlying WebSocket transport and marks the session closed locally.
|
|
538
|
+
* Does not wait for a graceful server acknowledgment.
|
|
556
539
|
*/
|
|
557
540
|
close(): void;
|
|
558
541
|
}
|
|
@@ -563,49 +546,43 @@ type Conversation = {
|
|
|
563
546
|
ended_at?: Date
|
|
564
547
|
};
|
|
565
548
|
/**
|
|
566
|
-
* Configuration for
|
|
549
|
+
* Configuration parameters for fetching a list of past conversations.
|
|
567
550
|
*/
|
|
568
551
|
type ConversationListParams = {
|
|
569
|
-
/** Agent ID to filter by */
|
|
552
|
+
/** Agent ID to filter the conversations by */
|
|
570
553
|
agentId: string
|
|
571
|
-
/** Number of results per page */
|
|
554
|
+
/** Number of results per page (defaults to 20) */
|
|
572
555
|
limit?: number
|
|
573
|
-
/** Page number
|
|
556
|
+
/** Page number, 1-indexed (defaults to 1) */
|
|
574
557
|
page?: number
|
|
575
558
|
};
|
|
576
559
|
/**
|
|
577
|
-
*
|
|
560
|
+
* Configuration parameters for connecting to an agent and establishing a session.
|
|
578
561
|
*/
|
|
579
562
|
type ConversationConnectParams = ConversationSessionConfig & {
|
|
580
|
-
/**
|
|
563
|
+
/** The unique ID of the agent to connect to */
|
|
581
564
|
agentId: string
|
|
582
565
|
/**
|
|
583
|
-
* Optional callback
|
|
584
|
-
*
|
|
566
|
+
* Optional callback invoked during the initial handshake phase.
|
|
567
|
+
* Can be used to hook into successful or failed connection attempts before the session object is returned.
|
|
585
568
|
*/
|
|
586
569
|
onConnection?: (event: ServerConnectionMessage) => void
|
|
587
570
|
};
|
|
588
571
|
/**
|
|
589
|
-
* Client for managing
|
|
572
|
+
* Client service for managing conversational records and establishing real-time WebSocket sessions.
|
|
590
573
|
*
|
|
591
574
|
* @example
|
|
592
575
|
* ```ts
|
|
593
|
-
* //
|
|
594
|
-
* const conversations = await kivox.conversations.list();
|
|
595
|
-
*
|
|
596
|
-
* // Connect to an agent
|
|
576
|
+
* // Connect to a Kivox agent
|
|
597
577
|
* const session = await kivox.conversations.connect({
|
|
598
|
-
*
|
|
599
|
-
*
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
* break;
|
|
607
|
-
* }
|
|
608
|
-
* }
|
|
578
|
+
* agentId: 'agent-123',
|
|
579
|
+
* onEvent: (event) => {
|
|
580
|
+
* if (event.type === 'text_delta') {
|
|
581
|
+
* console.log(event.chunk);
|
|
582
|
+
* } else if (event.type === 'audio_delta') {
|
|
583
|
+
* audioPlayer.enqueue(event.audio);
|
|
584
|
+
* }
|
|
585
|
+
* }
|
|
609
586
|
* });
|
|
610
587
|
*
|
|
611
588
|
* session.sendText('Hello!');
|
|
@@ -614,27 +591,33 @@ type ConversationConnectParams = ConversationSessionConfig & {
|
|
|
614
591
|
declare class ConversationClient {
|
|
615
592
|
private readonly http;
|
|
616
593
|
private readonly ws;
|
|
594
|
+
/**
|
|
595
|
+
* Instantiates a new ConversationClient.
|
|
596
|
+
* @param http The HTTP transport for REST endpoints.
|
|
597
|
+
* @param ws The WebSocket transport factory.
|
|
598
|
+
*/
|
|
617
599
|
constructor(http: HttpTransport, ws: WebSocketTransport);
|
|
618
600
|
/**
|
|
619
|
-
*
|
|
601
|
+
* Retrieves a paginated list of past conversations for a specific agent.
|
|
620
602
|
*
|
|
621
|
-
* @param params
|
|
622
|
-
* @returns
|
|
603
|
+
* @param params Query parameters for pagination and filtering.
|
|
604
|
+
* @returns A promise resolving to a paginated list of conversations.
|
|
623
605
|
*/
|
|
624
606
|
list(params: ConversationListParams): Promise<Paginated<Conversation[]>>;
|
|
625
607
|
/**
|
|
626
|
-
*
|
|
608
|
+
* Retrieves the details of a single conversation by its ID.
|
|
627
609
|
*
|
|
628
|
-
* @param id
|
|
629
|
-
* @returns
|
|
610
|
+
* @param id The unique identifier of the conversation.
|
|
611
|
+
* @returns A promise resolving to the conversation data.
|
|
630
612
|
*/
|
|
631
613
|
get(id: string): Promise<Conversation>;
|
|
632
614
|
/**
|
|
633
|
-
*
|
|
615
|
+
* Establishes a real-time WebSocket session with an agent.
|
|
616
|
+
* Handles the handshake protocol and returns an active session instance.
|
|
634
617
|
*
|
|
635
|
-
* @param params
|
|
636
|
-
* @returns
|
|
637
|
-
* @throws {Error} If handshake fails or connection
|
|
618
|
+
* @param params Configuration for the connection and subsequent session.
|
|
619
|
+
* @returns A promise resolving to an active `ConversationSession`.
|
|
620
|
+
* @throws {Error} If the handshake fails or the connection drops during negotiation.
|
|
638
621
|
*/
|
|
639
622
|
connect(params: ConversationConnectParams): Promise<ConversationSession>;
|
|
640
623
|
}
|
|
@@ -689,11 +672,11 @@ type Template = {
|
|
|
689
672
|
id: string
|
|
690
673
|
name: string
|
|
691
674
|
description?: string
|
|
692
|
-
|
|
675
|
+
ork_source: string
|
|
693
676
|
created_at: Date
|
|
694
677
|
updated_at: Date
|
|
695
678
|
};
|
|
696
|
-
type TemplateCreate = Pick<Template, "name" | "description" | "
|
|
679
|
+
type TemplateCreate = Pick<Template, "name" | "description" | "ork_source">;
|
|
697
680
|
type TemplateUpdate = Partial<TemplateCreate>;
|
|
698
681
|
/**
|
|
699
682
|
* Configuration for listing templates.
|
|
@@ -705,7 +688,7 @@ type TemplateListParams = {
|
|
|
705
688
|
page?: number
|
|
706
689
|
};
|
|
707
690
|
/**
|
|
708
|
-
* Client for interacting with
|
|
691
|
+
* Client for interacting with Kivox templates.
|
|
709
692
|
*
|
|
710
693
|
* @example
|
|
711
694
|
* ```ts
|
|
@@ -757,7 +740,7 @@ declare class TemplateClient {
|
|
|
757
740
|
*/
|
|
758
741
|
type KivoxConfig = {
|
|
759
742
|
/**
|
|
760
|
-
* Base URL of your self-hosted
|
|
743
|
+
* Base URL of your self-hosted Kivox instance.
|
|
761
744
|
* @example 'http://localhost:8787'
|
|
762
745
|
* @example 'https://api.kivox.io'
|
|
763
746
|
*/
|
|
@@ -769,8 +752,8 @@ type KivoxConfig = {
|
|
|
769
752
|
headers?: Record<string, string>
|
|
770
753
|
};
|
|
771
754
|
/**
|
|
772
|
-
* Main
|
|
773
|
-
* Provides unified access to all
|
|
755
|
+
* Main Kivox client.
|
|
756
|
+
* Provides unified access to all Kivox resources.
|
|
774
757
|
*
|
|
775
758
|
* @example
|
|
776
759
|
* ```ts
|
|
@@ -803,4 +786,4 @@ declare class KivoxClient {
|
|
|
803
786
|
readonly messages: MessageClient;
|
|
804
787
|
constructor(config: KivoxConfig);
|
|
805
788
|
}
|
|
806
|
-
export { TemplateUpdate, TemplateCreate, Template, SessionConnectionLostEvent,
|
|
789
|
+
export { TemplateUpdate, TemplateCreate, Template, SessionConnectionLostEvent, ServerTurnComplete, ServerTick, ServerTextFull, ServerTextDelta, ServerSessionEvent, ServerSessionClosed, ServerMessage, ServerHandshakeOK, ServerHandshakeError, ServerFlowComplete, ServerError, ServerConnectionMessage, ServerAudioDelta, Paginated, MessageRole, Message, KivoxConfig, KivoxClient, HttpTransportError, ConversationTransportError, ConversationSessionConfig, ConversationSession, Conversation, ClientMessage, ClientInputText, ClientInputAudioStream, ClientInputAudio, ClientHandshake, ClientEndSession, ClientCancel, AgentUpdate, AgentStatus, AgentSecret, AgentCreate, AgentConfig, AgentCompilationDiagnostic, Agent };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class
|
|
1
|
+
class z{http;constructor(_){this.http=_}async list(_={}){let x={limit:(_.limit??10).toString(),page:(_.page??1).toString()};if(_.search)x.search=_.search;let D=await this.http.get("/agents",x);return{...D,items:z.parseAgents(D.items)}}async listLive(_={}){let x={limit:(_.limit??10).toString(),page:(_.page??1).toString()};if(_.search)x.search=_.search;let D=await this.http.get("/agents/live",x);return{...D,items:z.parseAgents(D.items)}}async listDraft(_={}){let x={limit:(_.limit??10).toString(),page:(_.page??1).toString()};if(_.search)x.search=_.search;let D=await this.http.get("/agents/draft",x);return{...D,items:z.parseAgents(D.items)}}async listArchived(_={}){let x={limit:(_.limit??10).toString(),page:(_.page??1).toString()};if(_.search)x.search=_.search;let D=await this.http.get("/agents/archived",x);return{...D,items:z.parseAgents(D.items)}}async get(_){let x=await this.http.get(`/agents/${_}`);return z.parseAgent(x)}async create(_){let x=await this.http.post("/agents",_);return z.parseAgent(x)}async update(_,x){let D=await this.http.put(`/agents/${_}`,x);return z.parseAgent(D)}async markAsLive(_){let x=await this.http.patch(`/agents/${_}/live`);return z.parseAgent(x)}async markAsDraft(_){let x=await this.http.patch(`/agents/${_}/draft`);return z.parseAgent(x)}async markAsArchived(_){let x=await this.http.patch(`/agents/${_}/archived`);return z.parseAgent(x)}async delete(_){let x=await this.http.delete(`/agents/${_}`);return z.parseAgent(x)}async compile(_,x){return await this.http.post(`/agents/${_}/compile`,{ork_source:x})}static parseAgents(_){return _.map(z.parseAgent)}static parseAgent(_){return{..._,config:JSON.parse(_.config),secrets:JSON.parse(_.secrets)}}}class Q{_transport;_conversationId;_closed=!1;_onEvent;_pendingAudioMetadata=null;_remainingMs=0;_elapsedMs=0;get conversationId(){return this._conversationId}get remainingMs(){return this._remainingMs}get elapsedMs(){return this._elapsedMs}get closed(){return this._closed}constructor(_,x,D){this._transport=_,this._conversationId=x,this._onEvent=D.onEvent,this.#_()}sendText(_){if(this._closed){console.warn("Cannot send text: session is closed");return}this._transport.send({type:"input_text",text:_})}sendAudio(_){if(this._closed){console.warn("Cannot send audio: session is closed");return}this._transport.send({type:"input_audio"}),this._transport.sendBinary(_)}streamAudio(_){if(this._closed){console.warn("Cannot stream audio: session is closed");return}this._transport.send({type:"input_audio_stream"}),this._transport.sendBinary(_)}cancelRequest(){if(this._closed){console.warn("Cannot cancel request: session is closed");return}this._transport.send({type:"cancel"})}end(){if(this._closed){console.warn("Cannot end session: session is closed");return}this._transport.send({type:"end"})}close(){if(this._closed)return;this._closed=!0,this._transport.close()}#_(){this._transport.onMessage((_)=>{let x=_;if(x.type==="audio_delta"){this._pendingAudioMetadata={size:x.size};return}if(x.type==="tick")this._remainingMs=x.remaining_ms,this._elapsedMs=x.elapsed_ms;if(x.type==="session_closed")this._closed=!0;this._onEvent?.(x)}),this._transport.onBinary((_)=>{if(this._pendingAudioMetadata){let x={type:"audio_delta",size:this._pendingAudioMetadata.size,audio:_};this._pendingAudioMetadata=null,this._onEvent?.(x)}}),this._transport.onClose(()=>{if(this._closed)return;this._closed=!0,this._onEvent?.({type:"connection_lost",reason:"socket_closed"})}),this._transport.onError(()=>{if(this._closed)return;this._closed=!0,this._onEvent?.({type:"connection_lost",reason:"socket_error"})})}}class B extends Error{code;constructor(_,x="TRANSPORT_ERROR"){super(_);this.code=x;this.name="ConversationTransportError"}}class V{_ws;_closed=!1;_onMessage=null;_onBinary=null;_onError=null;_onClose=null;constructor(_){this._ws=_}async connect(){if(this._ws.readyState===WebSocket.OPEN)throw new B("Already connected","ALREADY_CONNECTED");if(this._ws.readyState===WebSocket.CLOSING||this._ws.readyState===WebSocket.CLOSED)throw new B("Socket is closing or closed","SOCKET_CLOSED");return new Promise((_,x)=>{let D=()=>{this._ws.removeEventListener("open",D),this._ws.removeEventListener("error",K),this.#_(),_()},K=()=>{this._ws.removeEventListener("open",D),this._ws.removeEventListener("error",K),x(new B("Connection failed","CONNECTION_FAILED"))};this._ws.addEventListener("open",D),this._ws.addEventListener("error",K)})}send(_){if(this._ws.readyState!==WebSocket.OPEN)throw new B("Not connected","NOT_CONNECTED");this._ws.send(JSON.stringify(_))}async sendBinary(_){if(this._ws.readyState!==WebSocket.OPEN)throw new B("Not connected","NOT_CONNECTED");let x=await _.arrayBuffer();this._ws.send(x)}onMessage(_){this._onMessage=_}onBinary(_){this._onBinary=_}onError(_){this._onError=_}onClose(_){this._onClose=_}close(){if(this._closed)return;if(this._closed=!0,this._ws.readyState===WebSocket.OPEN||this._ws.readyState===WebSocket.CONNECTING)this._ws.close();this._onClose?.()}#_(){this._ws.addEventListener("message",(_)=>{if(_.data instanceof Blob)this._onBinary?.(_.data);else if(_.data instanceof ArrayBuffer)this._onBinary?.(new Blob([_.data]));else if(typeof _.data==="string")try{let x=JSON.parse(_.data);this._onMessage?.(x)}catch(x){console.warn("Failed to parse JSON message:",_.data,x)}}),this._ws.addEventListener("error",()=>{if(this._closed)return;this._onError?.(new B("WebSocket error")),this.close()}),this._ws.addEventListener("close",()=>{if(this._closed)return;this.close()})}}class X{http;ws;constructor(_,x){this.http=_;this.ws=x}async list(_){let x={limit:(_.limit??20).toString(),page:(_.page??1).toString()};return this.http.get(`/agents/${_.agentId}/conversations`,x)}async get(_){return this.http.get(`/conversations/${_}`)}async connect(_){let x=this.ws.connect("/conversations/websocket"),D=new V(x);return await D.connect(),D.send({type:"handshake",agent_id:_.agentId}),new Promise((K,F)=>{let N=!1;D.onMessage((J)=>{switch(J.type){case"handshake_ok":N=!0,_.onConnection?.(J),K(new Q(D,J.conversation_id,_));break;case"handshake_error":N=!0,_.onConnection?.(J),D.close(),F(Error(`Handshake rejected: ${J.reason}`));break;default:break}}),D.onError((J)=>{if(!N)F(J)}),D.onClose(()=>{if(!N)F(Error("WebSocket connection lost during handshake"))})})}}function L(_){let x=new URL(_),D=x.protocol==="https:"?"wss:":"ws:";return{rest:`${x.origin}/v1`,ws:`${D}//${x.host}/v1`}}class Y extends Error{status;statusText;body;constructor(_,x,D,K){super(_);this.status=x;this.statusText=D;this.body=K;this.name="HttpTransportError"}}class Z{config;constructor(_){this.config=_}async request(_,x){let D=`${this.config.baseUrl}${_}`,K=await fetch(D,{...x,headers:{"Content-Type":"application/json",...this.config.headers,...x?.headers}});if(!K.ok){let F=await K.text();throw new Y(`HTTP ${K.status}: ${K.statusText}`,K.status,K.statusText,F)}return K.json()}async get(_,x){let D=new URL(`${this.config.baseUrl}${_}`);if(x){let K=Object.entries(x);for(let[F,N]of K)D.searchParams.set(F,N)}return this.request(_+D.search,{method:"GET"})}async post(_,x){return this.request(_,{method:"POST",body:x?JSON.stringify(x):void 0})}async put(_,x){return this.request(_,{method:"PUT",body:x?JSON.stringify(x):void 0})}async patch(_,x){return this.request(_,{method:"PATCH",body:x?JSON.stringify(x):void 0})}async delete(_){return this.request(_,{method:"DELETE"})}}class ${config;constructor(_){this.config=_}connect(_){let x=`${this.config.baseUrl}${_}`;return new WebSocket(x)}}class G{http;constructor(_){this.http=_}async list(_={}){let x={limit:(_.limit??50).toString(),page:(_.page??1).toString()};if(_.conversationId)x.conversation_id=_.conversationId;return this.http.get("/messages",x)}async get(_){return this.http.get(`/messages/${_}`)}}class M{http;constructor(_){this.http=_}async list(_={}){let x={limit:(_.limit??10).toString(),page:(_.page??1).toString()};return this.http.get("/templates",x)}async get(_){return this.http.get(`/templates/${_}`)}async create(_){return this.http.post("/templates",_)}async update(_,x){return this.http.put(`/templates/${_}`,x)}async delete(_){return this.http.delete(`/templates/${_}`)}}class O{agents;conversations;templates;messages;constructor(_){let x=L(_.baseUrl),D=new Z({baseUrl:x.rest,headers:_.headers}),K=new $({baseUrl:x.ws,headers:_.headers});this.agents=new z(D),this.templates=new M(D),this.conversations=new X(D,K),this.messages=new G(D)}}export{O as KivoxClient,Y as HttpTransportError,B as ConversationTransportError,Q as ConversationSession};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kivox/client",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
4
|
-
"description": "JavaScript/TypeScript client for
|
|
3
|
+
"version": "0.1.0-beta.21",
|
|
4
|
+
"description": "JavaScript/TypeScript client for Kivox",
|
|
5
5
|
"homepage": "https://github.com/ekisa-team/kivox#readme",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/ekisa-team/kivox/issues"
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"email": "ju4n97@proton.me",
|
|
16
16
|
"url": "https://github.com/ju4n97"
|
|
17
17
|
},
|
|
18
|
-
"sideEffects": false,
|
|
19
18
|
"type": "module",
|
|
20
19
|
"exports": {
|
|
21
20
|
".": {
|
|
@@ -42,6 +41,7 @@
|
|
|
42
41
|
"typescript": "5.9.3"
|
|
43
42
|
},
|
|
44
43
|
"publishConfig": {
|
|
45
|
-
"access": "public"
|
|
44
|
+
"access": "public",
|
|
45
|
+
"tag": "latest"
|
|
46
46
|
}
|
|
47
47
|
}
|