@jivaai/agent-chat-typescript 0.1.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 ADDED
@@ -0,0 +1,793 @@
1
+ # Jiva.ai Agent Chat - TypeScript SDK
2
+
3
+ A comprehensive TypeScript SDK for integrating with Jiva.ai's agentic workflows. This library provides a simple, type-safe interface for building conversational AI applications powered by Jiva.ai's agentic workflow engine.
4
+
5
+ ## Features
6
+
7
+ - 🤖 **Full Agentic Workflow Integration** - Seamlessly interact with Jiva.ai's agentic workflows
8
+ - 💬 **Conversational Interface** - Support for multi-turn conversations with context
9
+ - 📤 **Asset Upload Support** - Upload files, text, and tables to satisfy agent requirements
10
+ - 🔄 **Automatic Polling** - Handles async workflow execution with automatic polling
11
+ - 📡 **Real-Time Updates** - Subscribe to live agent updates via Server-Sent Events (SSE)
12
+ - 🎯 **Type-Safe** - Full TypeScript support with comprehensive type definitions
13
+ - 📝 **Built-in Logging** - Configurable logging for debugging and monitoring
14
+
15
+ ## Quick Start
16
+
17
+ ### 1. Installation
18
+
19
+ If you're using this package from npm:
20
+
21
+ ```bash
22
+ npm install @jivaai/agent-chat-typescript
23
+ ```
24
+
25
+ If you're using this package directly from the repository:
26
+
27
+ ```bash
28
+ cd agent-chat/typescript
29
+ npm install
30
+ npm run build
31
+ ```
32
+
33
+ ### 2. Get Your Credentials
34
+
35
+ Before you can use the SDK, you'll need to obtain the following from your Jiva.ai platform project:
36
+
37
+ 1. **Main Chat Workflow ID** - The workflow ID for your agent chat backend
38
+ 2. **API Key** - Your API key for authentication
39
+ 3. **Upload Cache Workflow IDs** - Workflow IDs for:
40
+ - File Upload Cache
41
+ - Text Upload Cache
42
+ - Table Upload Cache
43
+
44
+ These can be found in your Jiva.ai platform project settings. The upload cache workflows are typically created alongside your main chat workflow.
45
+
46
+ ### 3. Create a Client Instance
47
+
48
+ ```typescript
49
+ import { JivaApiClient } from '@jivaai/agent-chat-typescript';
50
+
51
+ const client = new JivaApiClient({
52
+ // Required: Main chat workflow configuration
53
+ apiKey: 'your-api-key',
54
+ workflowId: 'your-workflow-id',
55
+ workflowVersion: '0', // Optional, defaults to "0"
56
+
57
+ // Required: Upload cache workflow IDs
58
+ fileUploadCacheWorkflowId: 'file-cache-workflow-id',
59
+ textUploadCacheWorkflowId: 'text-cache-workflow-id',
60
+ tableUploadCacheWorkflowId: 'table-cache-workflow-id',
61
+
62
+ // Optional: Upload cache versions (default to workflowVersion or "0")
63
+ fileUploadCacheVersion: '0',
64
+ textUploadCacheVersion: '0',
65
+ tableUploadCacheVersion: '0',
66
+
67
+ // Optional: Separate API keys for upload caches (default to apiKey)
68
+ fileUploadCacheApiKey: 'file-cache-api-key',
69
+ textUploadCacheApiKey: 'text-cache-api-key',
70
+ tableUploadCacheApiKey: 'table-cache-api-key',
71
+
72
+ // Optional: Custom base URLs (for testing or different environments)
73
+ baseUrl: 'https://api.jiva.ai/public-api/workflow',
74
+ socketBaseUrl: 'https://api.jiva.ai/public-api',
75
+
76
+ // Optional: Logging configuration
77
+ logging: {
78
+ level: 'info', // 'debug' | 'info' | 'warn' | 'error' | 'silent'
79
+ enabled: true,
80
+ },
81
+ });
82
+ ```
83
+
84
+ ### 4. Start a Conversation
85
+
86
+ ```typescript
87
+ // Initiate a conversation with the agent
88
+ const response = await client.initiateConversation({
89
+ sessionId: 'user-123-thread-1', // Unique session ID per user/thread
90
+ message: 'create a professional RFQ document', // obviously, this needs to be relevant to your agent
91
+ mode: 'CHAT_REQUEST',
92
+ });
93
+
94
+ // Handle the response
95
+ if (response.error) {
96
+ console.error('Error:', response.error);
97
+ } else if (response.data) {
98
+ const conversationData = response.data.json.default;
99
+
100
+ if (conversationData.state === 'OK') {
101
+ console.log('Success:', conversationData.message);
102
+
103
+ // Process execution results
104
+ if (conversationData.executions) {
105
+ conversationData.executions.forEach((exec) => {
106
+ console.log(`Execution: ${exec.response} (${exec.type})`);
107
+ });
108
+ }
109
+ } else if (conversationData.state === 'ERROR') {
110
+ console.error('Error:', response.data.errorMessages);
111
+ }
112
+ }
113
+ ```
114
+
115
+ That's it! The SDK automatically handles:
116
+ - ✅ Async workflow execution (polling when state is `RUNNING`)
117
+ - ✅ Error handling
118
+ - ✅ Response parsing
119
+
120
+ ## How the API Works
121
+
122
+ ### Architecture Overview
123
+
124
+ The Jiva.ai Agent Chat SDK communicates with Jiva.ai's agentic workflow engine through REST APIs and Server-Sent Events (SSE):
125
+
126
+ 1. **Main Chat Workflow** - Handles conversation requests and agent interactions
127
+ 2. **Upload Cache Workflows** - Store uploaded assets (files, text, tables) that agents can reference
128
+ 3. **EventSource (SSE)** - Provides real-time updates during agent processing
129
+
130
+ ### Request Flow
131
+
132
+ ```
133
+ ┌─────────────┐
134
+ │ Your App │
135
+ └──────┬──────┘
136
+
137
+ │ 1. initiateConversation()
138
+
139
+ ┌─────────────────────────┐
140
+ │ JivaApiClient │
141
+ │ - Validates request │
142
+ │ - Sends POST request │
143
+ └──────┬──────────────────┘
144
+
145
+ │ 2. POST /workflow/{workflowId}/{version}/invoke
146
+
147
+ ┌─────────────────────────┐
148
+ │ Jiva.ai API │
149
+ │ - Processes request │
150
+ │ - Returns state: │
151
+ │ • OK (immediate) │
152
+ │ • RUNNING (async) │
153
+ │ • ERROR │
154
+ └──────┬──────────────────┘
155
+
156
+ │ 3. If RUNNING, auto-poll
157
+
158
+ ┌─────────────────────────┐
159
+ │ Polling (automatic) │
160
+ │ - Polls every 1s │
161
+ │ - Max 30 attempts │
162
+ │ - Returns when complete │
163
+ └─────────────────────────┘
164
+ ```
165
+
166
+ ### Response States
167
+
168
+ The API returns responses with different states:
169
+
170
+ - **OK** - Request processed immediately, result is available
171
+ - **RUNNING** - Request is being processed asynchronously (SDK automatically polls)
172
+ - **PARTIAL_OK** - Partial results are available
173
+ - **ERROR** - Request failed with an error
174
+
175
+ ### Response Modes
176
+
177
+ - **CHAT_RESPONSE** - Normal response with execution results
178
+ - **SCREEN_RESPONSE** - Response indicating that assets are required (check `screens` array)
179
+
180
+ ## Usage Guide
181
+
182
+ ### Basic Conversation
183
+
184
+ The simplest way to interact with the agent:
185
+
186
+ ```typescript
187
+ const response = await client.initiateConversation({
188
+ sessionId: 'user-123-thread-1',
189
+ message: 'Hello, what can you help me with?',
190
+ mode: 'CHAT_REQUEST',
191
+ });
192
+
193
+ if (response.data?.json.default.state === 'OK') {
194
+ console.log('Agent response:', response.data.json.default.message);
195
+ }
196
+ ```
197
+
198
+ ### Conversations with Context
199
+
200
+ Provide conversation history for context-aware interactions:
201
+
202
+ ```typescript
203
+ const response = await client.initiateConversation(
204
+ [
205
+ {
206
+ sessionId: 'user-123-thread-1',
207
+ message: 'RFQs are generally single-pagers',
208
+ mode: 'CHAT_REQUEST',
209
+ },
210
+ {
211
+ sessionId: 'user-123-thread-1',
212
+ message: 'ok',
213
+ mode: 'CHAT_RESPONSE',
214
+ },
215
+ {
216
+ sessionId: 'user-123-thread-1',
217
+ message: 'create a professional RFQ document',
218
+ mode: 'CHAT_REQUEST',
219
+ },
220
+ ],
221
+ {
222
+ maxAttempts: 30, // Optional: max polling attempts (default: 30)
223
+ pollInterval: 1000, // Optional: polling interval in ms (default: 1000)
224
+ }
225
+ );
226
+ ```
227
+
228
+ **Important Notes:**
229
+ - All messages must have the same `sessionId`
230
+ - `CHAT_REQUEST` and `CHAT_RESPONSE` must alternate in the array
231
+ - The first message can be either `CHAT_REQUEST` or `CHAT_RESPONSE`
232
+
233
+ ### Handling Screen Responses
234
+
235
+ Sometimes the agent requires additional assets (like files) to complete a request. When this happens, the response will have `mode: 'SCREEN_RESPONSE'` and include a `screens` array.
236
+
237
+ ```typescript
238
+ const response = await client.initiateConversation({
239
+ sessionId: 'session-123',
240
+ message: 'create a professional RFQ document',
241
+ mode: 'CHAT_REQUEST',
242
+ });
243
+
244
+ if (response.data?.json.default.mode === 'SCREEN_RESPONSE') {
245
+ const screens = response.data.json.default.screens;
246
+
247
+ screens?.forEach((screen) => {
248
+ console.log(`Screen ${screen.nodeId}: ${screen.asset.message}`);
249
+ console.log(`Asset type: ${screen.asset.type}`);
250
+
251
+ if (screen.asset.type === 'FILE_UPLOAD') {
252
+ // Upload file and satisfy the screen (see below)
253
+ }
254
+ });
255
+ }
256
+ ```
257
+
258
+ ### Uploading Assets
259
+
260
+ The SDK provides methods to upload files, text, and tables. These methods return an `assetId` that can be used to satisfy screen responses.
261
+
262
+ #### Uploading a File
263
+
264
+ ```typescript
265
+ // In browser environments, you can upload File or Blob objects
266
+ const file = new File(['file content'], 'document.pdf', {
267
+ type: 'application/pdf'
268
+ });
269
+
270
+ const uploadResponse = await client.uploadFile(file);
271
+
272
+ if (uploadResponse.data) {
273
+ const assetId = uploadResponse.data.strings.default;
274
+ console.log('File uploaded, assetId:', assetId);
275
+ // Cache this assetId for later use with the same sessionId
276
+ }
277
+ ```
278
+
279
+ ```typescript
280
+ // In Node.js environments, provide base64 string directly
281
+ const base64String = 'base64-encoded-file-content';
282
+ const uploadResponse = await client.uploadFile(base64String);
283
+
284
+ const assetId = uploadResponse.data?.strings.default;
285
+ ```
286
+
287
+ #### Uploading Text
288
+
289
+ ```typescript
290
+ const textResponse = await client.uploadText(
291
+ 'This is the text content to upload'
292
+ );
293
+
294
+ const assetId = textResponse.data?.strings.default;
295
+ ```
296
+
297
+ #### Uploading Table Data
298
+
299
+ ```typescript
300
+ const tableData = [
301
+ { name: 'John', age: 30, city: 'New York' },
302
+ { name: 'Jane', age: 25, city: 'Boston' },
303
+ { name: 'Bob', age: 35, city: 'Chicago' },
304
+ ];
305
+
306
+ const tableResponse = await client.uploadTable(tableData);
307
+
308
+ const assetId = tableResponse.data?.strings.default;
309
+ ```
310
+
311
+ ### Satisfying Screen Responses
312
+
313
+ After uploading assets and receiving an `assetId`, you can satisfy the screen by including `nodeId`, `field`, and `assetId` in your follow-up request:
314
+
315
+ ```typescript
316
+ // 1. Make initial request
317
+ const response = await client.initiateConversation({
318
+ sessionId: 'session-123',
319
+ message: 'create a professional RFQ document',
320
+ mode: 'CHAT_REQUEST',
321
+ });
322
+
323
+ // 2. Check for screen response
324
+ if (response.data?.json.default.mode === 'SCREEN_RESPONSE') {
325
+ const screen = response.data.json.default.screens?.[0];
326
+
327
+ if (screen?.asset.type === 'FILE_UPLOAD') {
328
+ // 3. Upload the file
329
+ const file = /* get file from user */;
330
+ const uploadResponse = await client.uploadFile(file);
331
+
332
+ if (uploadResponse.data) {
333
+ const assetId = uploadResponse.data.strings.default;
334
+
335
+ // 4. Satisfy the screen with the uploaded asset
336
+ const followUp = await client.initiateConversation({
337
+ sessionId: 'session-123',
338
+ message: 'create a professional RFQ document',
339
+ mode: 'CHAT_REQUEST',
340
+ nodeId: screen.nodeId,
341
+ field: screen.field,
342
+ assetId: assetId,
343
+ });
344
+ }
345
+ }
346
+ }
347
+ ```
348
+
349
+ **Important Notes:**
350
+ - All three fields (`nodeId`, `field`, `assetId`) must be provided together when satisfying a screen
351
+ - The `nodeId` and `field` come from the `screens` array in the `SCREEN_RESPONSE`
352
+ - The `assetId` comes from uploading to File Upload Cache, Text Upload Cache, or Table Upload Cache endpoints
353
+ - Asset IDs should be cached on your backend - they can be reused for the same `sessionId`
354
+ - Asset semantics are session-specific: an asset for one `sessionId` may not be valid for another
355
+
356
+ ### Real-Time Updates with EventSource
357
+
358
+ Subscribe to real-time updates from the agent using Server-Sent Events (SSE). This allows you to receive live updates as the agent processes requests, including thinking messages, execution results, and progress updates.
359
+
360
+ ```typescript
361
+ // Subscribe to real-time updates for a session
362
+ const es = client.subscribeToSocket(
363
+ 'session-123', // Session ID
364
+ {
365
+ onOpen: () => {
366
+ console.log('EventSource connected');
367
+ },
368
+ onMessage: (message) => {
369
+ console.log('Message:', message.message);
370
+ console.log('Types:', message.types);
371
+
372
+ // Handle different message types
373
+ if (message.types.includes('AGENT_THINKING')) {
374
+ console.log('Agent is thinking...');
375
+ } else if (message.types.includes('AGENT_COMPLETED')) {
376
+ console.log('Agent completed successfully');
377
+ } else if (message.types.includes('CONTENT_DELTA')) {
378
+ // Streaming content
379
+ process.stdout.write(message.message);
380
+ } else if (message.types.includes('FINAL_RESULT')) {
381
+ console.log('Final result:', message.message);
382
+ }
383
+ },
384
+ onClose: (event) => {
385
+ console.log('EventSource closed:', event.reason);
386
+ },
387
+ onError: (error) => {
388
+ console.error('EventSource error:', error);
389
+ },
390
+ onReconnect: (attempt) => {
391
+ console.log(`Reconnecting... (attempt ${attempt})`);
392
+ },
393
+ },
394
+ {
395
+ autoReconnect: true, // Automatically reconnect on disconnect
396
+ reconnectInterval: 3000, // Wait 3 seconds between reconnection attempts
397
+ maxReconnectAttempts: 10, // Maximum number of reconnection attempts
398
+ }
399
+ );
400
+
401
+ // Close the connection when done
402
+ es.close();
403
+ ```
404
+
405
+ #### Socket Message Types
406
+
407
+ The socket can send various message types. Here are some common ones:
408
+
409
+ - **AGENT_STARTED** - Agent has begun processing
410
+ - **AGENT_THINKING** - Agent is analyzing and planning
411
+ - **AGENT_COMPLETED** - Agent finished successfully
412
+ - **AGENT_FAILED** - Agent encountered an error
413
+ - **CONTENT_DELTA** - Incremental text content (streaming)
414
+ - **CONTENT_COMPLETE** - Full text content block
415
+ - **EXECUTION_CALL_STARTED** - Agent is invoking a pipeline
416
+ - **EXECUTION_CALL_RESULT** - Result from an execution
417
+ - **FINAL_RESULT** - Final output from the pipeline
418
+ - **PROGRESS_UPDATE** - Progress percentage or status
419
+ - **TOKEN_USAGE** - Token consumption metrics
420
+ - **ERROR** - Error message with details
421
+ - **KEEPALIVE** - Heartbeat to keep connection alive
422
+
423
+ And many more. See the full list in the type definitions.
424
+
425
+ #### Socket Options
426
+
427
+ - **autoReconnect** (default: `true`) - Automatically attempt to reconnect on disconnect
428
+ - **reconnectInterval** (default: `3000`) - Delay in milliseconds between reconnection attempts
429
+ - **maxReconnectAttempts** (default: `10`) - Maximum number of reconnection attempts before giving up
430
+
431
+ #### Example: Real-Time Chat with EventSource
432
+
433
+ ```typescript
434
+ // Start a conversation
435
+ const response = await client.initiateConversation({
436
+ sessionId: 'session-123',
437
+ message: 'create a professional RFQ document',
438
+ mode: 'CHAT_REQUEST',
439
+ });
440
+
441
+ // Subscribe to real-time updates
442
+ const es = client.subscribeToSocket('session-123', {
443
+ onMessage: (message) => {
444
+ if (message.types.includes('CONTENT_DELTA')) {
445
+ // Stream content to user
446
+ updateUI(message.message);
447
+ } else if (message.types.includes('AGENT_COMPLETED')) {
448
+ console.log('Agent finished processing');
449
+ es.close();
450
+ } else if (message.types.includes('ERROR')) {
451
+ console.error('Error:', message.message);
452
+ es.close();
453
+ }
454
+ },
455
+ });
456
+ ```
457
+
458
+ **Note:**
459
+ - The EventSource URL is constructed from the `socketBaseUrl` (defaults to `https://api.jiva.ai/public-api`) and follows the pattern: `{socketBaseUrl}/workflow-chat/{workflowId}/{sessionId}`
460
+ - API endpoints follow the pattern: `{baseUrl}/{workflowId}/{version}/invoke` where version defaults to "0"
461
+ - For test environments, you can set custom `baseUrl` and version numbers in the client configuration
462
+
463
+ ### Manual Polling
464
+
465
+ If you need to manually poll for a result (e.g., for multiple IDs simultaneously), you can use the `poll()` method:
466
+
467
+ ```typescript
468
+ // Poll for a specific execution ID
469
+ const pollResponse = await client.poll(
470
+ {
471
+ sessionId: 'user-123-thread-1', // Required: session ID from original request
472
+ id: 'exec-456', // Required: ID from the RUNNING response
473
+ mode: 'POLL_REQUEST', // Required: must be POLL_REQUEST
474
+ },
475
+ (data) => {
476
+ // Success callback (optional)
477
+ console.log('State:', data.json.default.state);
478
+ if (data.json.default.logs) {
479
+ console.log('Logs:', data.json.default.logs);
480
+ }
481
+ if (data.json.default.executions) {
482
+ data.json.default.executions.forEach((exec) => {
483
+ console.log(`Execution state: ${exec.output.state}`);
484
+ console.log(`Output: ${exec.output.response} (${exec.output.type})`);
485
+ });
486
+ }
487
+ },
488
+ (error) => {
489
+ // Error callback (optional)
490
+ console.error('Error:', error);
491
+ }
492
+ );
493
+
494
+ // Handle the response
495
+ if (pollResponse.error) {
496
+ console.error('Poll failed:', pollResponse.error);
497
+ } else if (pollResponse.data) {
498
+ const pollData = pollResponse.data.json.default;
499
+
500
+ if (pollData.state === 'OK') {
501
+ console.log('Processing complete!');
502
+ } else if (pollData.state === 'RUNNING') {
503
+ console.log('Still processing...');
504
+ // Poll again after recommended 1 second delay
505
+ } else if (pollData.state === 'PARTIAL_OK') {
506
+ console.log('Partial results available');
507
+ } else if (pollData.state === 'ERROR') {
508
+ console.error('Error:', pollResponse.data.errorMessages);
509
+ }
510
+ }
511
+ ```
512
+
513
+ **Note**: Only 1 sessionId can be polled per call. If you need to poll multiple IDs, make separate API calls simultaneously. The recommended polling frequency is 1 second to avoid being blacklisted.
514
+
515
+ ### Using Promises (without callbacks)
516
+
517
+ All methods return promises, so you can use async/await or `.then()`:
518
+
519
+ ```typescript
520
+ // The methods return promises, so you can use async/await or .then()
521
+ const response = await client.post({ message: 'Hello' });
522
+
523
+ if (response.error) {
524
+ console.error('Error:', response.error);
525
+ } else {
526
+ console.log('Data:', response.data);
527
+ }
528
+ ```
529
+
530
+ ### Logging
531
+
532
+ The SDK includes built-in logging with different log levels. By default, logging is enabled and uses:
533
+ - **Production**: `warn` level (warnings and errors only)
534
+ - **Development**: `debug` level (all messages)
535
+
536
+ You can configure logging in the client initialization:
537
+
538
+ ```typescript
539
+ const client = new JivaApiClient({
540
+ apiKey: 'your-api-key',
541
+ workflowId: 'your-workflow-id',
542
+ // ... other config ...
543
+ logging: {
544
+ level: 'debug', // 'debug' | 'info' | 'warn' | 'error' | 'silent'
545
+ enabled: true, // Enable/disable logging
546
+ },
547
+ });
548
+ ```
549
+
550
+ **Log Levels:**
551
+ - `debug`: Detailed information (URLs, payloads, responses) - most verbose
552
+ - `info`: General flow information (method calls, state changes)
553
+ - `warn`: Warnings (retries, fallbacks, timeouts)
554
+ - `error`: Errors (API errors, network errors)
555
+ - `silent`: No logging output
556
+
557
+ **Using a Custom Logger:**
558
+
559
+ You can provide your own logger implementation:
560
+
561
+ ```typescript
562
+ import { Logger } from '@jivaai/agent-chat-typescript';
563
+
564
+ const customLogger: Logger = {
565
+ debug(message: string, ...args: unknown[]): void {
566
+ // Your custom debug logging
567
+ },
568
+ info(message: string, ...args: unknown[]): void {
569
+ // Your custom info logging
570
+ },
571
+ warn(message: string, ...args: unknown[]): void {
572
+ // Your custom warn logging
573
+ },
574
+ error(message: string, ...args: unknown[]): void {
575
+ // Your custom error logging
576
+ },
577
+ };
578
+
579
+ const client = new JivaApiClient({
580
+ apiKey: 'your-api-key',
581
+ workflowId: 'your-workflow-id',
582
+ // ... other config ...
583
+ logging: {
584
+ logger: customLogger,
585
+ level: 'info',
586
+ },
587
+ });
588
+ ```
589
+
590
+ **Disable Logging:**
591
+
592
+ ```typescript
593
+ const client = new JivaApiClient({
594
+ apiKey: 'your-api-key',
595
+ workflowId: 'your-workflow-id',
596
+ // ... other config ...
597
+ logging: {
598
+ enabled: false, // Disable all logging
599
+ },
600
+ });
601
+ ```
602
+
603
+ ### Using Custom Base URL (for testing)
604
+
605
+ ```typescript
606
+ const testClient = new JivaApiClient({
607
+ apiKey: 'test-api-key',
608
+ workflowId: 'test-workflow-id',
609
+ fileUploadCacheWorkflowId: 'test-file-cache-workflow-id',
610
+ textUploadCacheWorkflowId: 'test-text-cache-workflow-id',
611
+ tableUploadCacheWorkflowId: 'test-table-cache-workflow-id',
612
+ baseUrl: 'https://test-api.example.com/workflow',
613
+ socketBaseUrl: 'https://test-api.example.com',
614
+ });
615
+ ```
616
+
617
+ ## Development
618
+
619
+ ### Build
620
+
621
+ ```bash
622
+ npm run build
623
+ ```
624
+
625
+ This compiles TypeScript to JavaScript in the `dist/` directory.
626
+
627
+ ### Test
628
+
629
+ ```bash
630
+ npm test
631
+ ```
632
+
633
+ Run tests in watch mode:
634
+
635
+ ```bash
636
+ npm run test:watch
637
+ ```
638
+
639
+ Run only end-to-end tests:
640
+
641
+ ```bash
642
+ npm test -- e2e.test.ts
643
+ ```
644
+
645
+ Run integration tests (requires local Jiva.ai instance):
646
+
647
+ ```bash
648
+ # Remove .skip from describe block in integration.test.ts first
649
+ npm test -- integration.test.ts
650
+ ```
651
+
652
+ Run integration tests (they are skipped by default):
653
+
654
+ ```bash
655
+ # On Unix/Linux/Mac:
656
+ RUN_INTEGRATION_TESTS=true npm test -- integration.test.ts
657
+
658
+ # On Windows (PowerShell):
659
+ $env:RUN_INTEGRATION_TESTS="true"; npm test -- integration.test.ts
660
+
661
+ # On Windows (CMD):
662
+ set RUN_INTEGRATION_TESTS=true && npm test -- integration.test.ts
663
+ ```
664
+
665
+ **Note**: Integration tests are skipped by default and require a running local Jiva.ai instance. They will only run when `RUN_INTEGRATION_TESTS=true` is explicitly set.
666
+
667
+ ### Lint
668
+
669
+ ```bash
670
+ npm run lint
671
+ ```
672
+
673
+ ## Project Structure
674
+
675
+ ```
676
+ typescript/
677
+ ├── src/ # Source code
678
+ │ ├── __tests__/ # Test files
679
+ │ ├── api.ts # Main API client implementation
680
+ │ ├── types.ts # TypeScript type definitions
681
+ │ ├── logger.ts # Logging utilities
682
+ │ └── index.ts # Main entry point
683
+ ├── dist/ # Compiled output (generated)
684
+ ├── package.json # Dependencies and scripts
685
+ ├── tsconfig.json # TypeScript configuration
686
+ └── jest.config.js # Jest test configuration
687
+ ```
688
+
689
+ ## API Reference
690
+
691
+ ### JivaApiClient
692
+
693
+ Main client class for interacting with the Jiva.ai Agent Chat API.
694
+
695
+ #### Constructor
696
+
697
+ ```typescript
698
+ new JivaApiClient(config: ApiConfig)
699
+ ```
700
+
701
+ #### Methods
702
+
703
+ ##### `initiateConversation(request, options?, onSuccess?, onError?)`
704
+
705
+ Initiates a conversation with the Jiva.ai agent.
706
+
707
+ - **request**: `InitiateConversationRequest | InitiateConversationWithContext` - Single message or array of messages
708
+ - **options**: `PollingOptions` (optional) - Polling configuration
709
+ - **onSuccess**: `SuccessCallback<ConversationResponse>` (optional) - Success callback
710
+ - **onError**: `ErrorCallback` (optional) - Error callback
711
+ - **Returns**: `Promise<ApiResponse<ConversationResponse>>`
712
+
713
+ ##### `poll(request, onSuccess?, onError?)`
714
+
715
+ Manually polls for the status of a running conversation.
716
+
717
+ - **request**: `PollRequest` - Poll request with sessionId, id, and mode
718
+ - **onSuccess**: `SuccessCallback<PollResponse>` (optional) - Success callback
719
+ - **onError**: `ErrorCallback` (optional) - Error callback
720
+ - **Returns**: `Promise<ApiResponse<PollResponse>>`
721
+
722
+ ##### `uploadFile(file, onSuccess?, onError?)`
723
+
724
+ Uploads a file to the File Upload Cache.
725
+
726
+ - **file**: `File | Blob | string` - File to upload (File/Blob in browser, base64 string in Node.js)
727
+ - **onSuccess**: `SuccessCallback<UploadResponse>` (optional) - Success callback
728
+ - **onError**: `ErrorCallback` (optional) - Error callback
729
+ - **Returns**: `Promise<ApiResponse<UploadResponse>>`
730
+
731
+ ##### `uploadText(text, onSuccess?, onError?)`
732
+
733
+ Uploads text to the Text Upload Cache.
734
+
735
+ - **text**: `string` - Text content to upload
736
+ - **onSuccess**: `SuccessCallback<UploadResponse>` (optional) - Success callback
737
+ - **onError**: `ErrorCallback` (optional) - Error callback
738
+ - **Returns**: `Promise<ApiResponse<UploadResponse>>`
739
+
740
+ ##### `uploadTable(tableData, onSuccess?, onError?)`
741
+
742
+ Uploads table data to the Table Upload Cache.
743
+
744
+ - **tableData**: `Record<string, unknown>[]` - Table data to upload
745
+ - **onSuccess**: `SuccessCallback<UploadResponse>` (optional) - Success callback
746
+ - **onError**: `ErrorCallback` (optional) - Error callback
747
+ - **Returns**: `Promise<ApiResponse<UploadResponse>>`
748
+
749
+ ##### `subscribeToSocket(sessionId, callbacks?, options?)`
750
+
751
+ Creates a Server-Sent Events (SSE) connection to subscribe to real-time agent updates.
752
+
753
+ - **sessionId**: `string` - Session ID to subscribe to
754
+ - **callbacks**: `SocketCallbacks` (optional) - Event callbacks
755
+ - **options**: `SocketOptions` (optional) - Socket connection options
756
+ - **Returns**: `{ url: string; close: () => void; readyState: number }`
757
+
758
+ ##### `get(endpoint?, onSuccess?, onError?)`
759
+
760
+ Makes a GET request to the API.
761
+
762
+ - **endpoint**: `string` (optional) - Endpoint path
763
+ - **onSuccess**: `SuccessCallback` (optional) - Success callback
764
+ - **onError**: `ErrorCallback` (optional) - Error callback
765
+ - **Returns**: `Promise<ApiResponse<T>>`
766
+
767
+ ##### `post(payload?, endpoint?, onSuccess?, onError?)`
768
+
769
+ Makes a POST request to the API.
770
+
771
+ - **payload**: `Record<string, unknown>` (optional) - JSON payload
772
+ - **endpoint**: `string` (optional) - Endpoint path
773
+ - **onSuccess**: `SuccessCallback` (optional) - Success callback
774
+ - **onError**: `ErrorCallback` (optional) - Error callback
775
+ - **Returns**: `Promise<ApiResponse<T>>`
776
+
777
+ ## Type Definitions
778
+
779
+ All TypeScript types are exported from the main entry point. Key types include:
780
+
781
+ - `ApiConfig` - Client configuration
782
+ - `InitiateConversationRequest` - Single conversation message
783
+ - `InitiateConversationWithContext` - Array of conversation messages
784
+ - `ConversationResponse` - Response from conversation request
785
+ - `PollRequest` - Poll request payload
786
+ - `PollResponse` - Poll response payload
787
+ - `UploadResponse` - Upload response payload
788
+ - `SocketMessage` - Real-time socket message
789
+ - `SocketCallbacks` - Socket event callbacks
790
+ - `SocketOptions` - Socket connection options
791
+ - `Logger` - Custom logger interface
792
+
793
+ See `src/types.ts` for complete type definitions.