@robosystems/client 0.2.10 → 0.2.12

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.
@@ -24,17 +24,30 @@ class QueryClient {
24
24
  mode: options.mode,
25
25
  test_mode: options.testMode,
26
26
  },
27
+ // For streaming mode, don't parse response - get raw Response object
28
+ ...(options.mode === 'stream' ? { parseAs: 'stream' } : {}),
27
29
  };
28
- // Execute the query
29
30
  const response = await (0, sdk_gen_1.executeCypherQuery)(data);
30
- // Check if this is an NDJSON streaming response
31
- // The SDK returns the response object which includes the raw Response
32
- if (response.response) {
31
+ // Check if this is a raw stream response (when parseAs: 'stream')
32
+ if (options.mode === 'stream' && response.response) {
33
33
  const contentType = response.response.headers.get('content-type') || '';
34
- const streamFormat = response.response.headers.get('x-stream-format');
35
- if (contentType.includes('application/x-ndjson') || streamFormat === 'ndjson') {
34
+ if (contentType.includes('application/x-ndjson')) {
36
35
  return this.parseNDJSONResponse(response.response, graphId);
37
36
  }
37
+ else if (contentType.includes('application/json')) {
38
+ // Fallback: parse JSON manually
39
+ const data = await response.response.json();
40
+ if (data.data !== undefined && data.columns) {
41
+ return {
42
+ data: data.data,
43
+ columns: data.columns,
44
+ row_count: data.row_count || data.data.length,
45
+ execution_time_ms: data.execution_time_ms || 0,
46
+ graph_id: graphId,
47
+ timestamp: data.timestamp || new Date().toISOString(),
48
+ };
49
+ }
50
+ }
38
51
  }
39
52
  const responseData = response.data;
40
53
  // Check if this is an immediate response
@@ -58,12 +71,7 @@ class QueryClient {
58
71
  throw new QueuedQueryError(queuedResponse);
59
72
  }
60
73
  // Use SSE to monitor the operation
61
- if (options.mode === 'stream') {
62
- return this.streamQueryResults(queuedResponse.operation_id, options);
63
- }
64
- else {
65
- return this.waitForQueryCompletion(queuedResponse.operation_id, options);
66
- }
74
+ return this.waitForQueryCompletion(queuedResponse.operation_id, options);
67
75
  }
68
76
  // Unexpected response format
69
77
  throw new Error('Unexpected response format from query endpoint');
@@ -73,35 +81,75 @@ class QueryClient {
73
81
  let columns = null;
74
82
  let totalRows = 0;
75
83
  let executionTimeMs = 0;
76
- // Parse NDJSON line by line
77
- const text = await response.text();
78
- const lines = text.trim().split('\n');
79
- for (const line of lines) {
80
- if (!line.trim())
81
- continue;
82
- try {
83
- const chunk = JSON.parse(line);
84
- // Extract columns from first chunk
85
- if (columns === null && chunk.columns) {
86
- columns = chunk.columns;
87
- }
88
- // Aggregate data rows (NDJSON uses "rows", regular JSON uses "data")
89
- if (chunk.rows) {
90
- allData.push(...chunk.rows);
91
- totalRows += chunk.rows.length;
84
+ // Use streaming reader to avoid "body already read" error
85
+ const reader = response.body?.getReader();
86
+ if (!reader) {
87
+ throw new Error('Response body is not readable');
88
+ }
89
+ const decoder = new TextDecoder();
90
+ let buffer = '';
91
+ try {
92
+ while (true) {
93
+ const { done, value } = await reader.read();
94
+ if (done)
95
+ break;
96
+ buffer += decoder.decode(value, { stream: true });
97
+ const lines = buffer.split('\n');
98
+ buffer = lines.pop() || '';
99
+ for (const line of lines) {
100
+ if (!line.trim())
101
+ continue;
102
+ try {
103
+ const chunk = JSON.parse(line);
104
+ // Extract columns from first chunk
105
+ if (columns === null && chunk.columns) {
106
+ columns = chunk.columns;
107
+ }
108
+ // Aggregate data rows (NDJSON uses "rows", regular JSON uses "data")
109
+ if (chunk.rows) {
110
+ allData.push(...chunk.rows);
111
+ totalRows += chunk.rows.length;
112
+ }
113
+ else if (chunk.data) {
114
+ allData.push(...chunk.data);
115
+ totalRows += chunk.data.length;
116
+ }
117
+ // Track execution time (use max from all chunks)
118
+ if (chunk.execution_time_ms) {
119
+ executionTimeMs = Math.max(executionTimeMs, chunk.execution_time_ms);
120
+ }
121
+ }
122
+ catch (error) {
123
+ console.error('Failed to parse NDJSON line:', error);
124
+ }
92
125
  }
93
- else if (chunk.data) {
94
- allData.push(...chunk.data);
95
- totalRows += chunk.data.length;
126
+ }
127
+ // Parse any remaining buffer
128
+ if (buffer.trim()) {
129
+ try {
130
+ const chunk = JSON.parse(buffer);
131
+ if (columns === null && chunk.columns) {
132
+ columns = chunk.columns;
133
+ }
134
+ if (chunk.rows) {
135
+ allData.push(...chunk.rows);
136
+ totalRows += chunk.rows.length;
137
+ }
138
+ else if (chunk.data) {
139
+ allData.push(...chunk.data);
140
+ totalRows += chunk.data.length;
141
+ }
142
+ if (chunk.execution_time_ms) {
143
+ executionTimeMs = Math.max(executionTimeMs, chunk.execution_time_ms);
144
+ }
96
145
  }
97
- // Track execution time (use max from all chunks)
98
- if (chunk.execution_time_ms) {
99
- executionTimeMs = Math.max(executionTimeMs, chunk.execution_time_ms);
146
+ catch (error) {
147
+ console.error('Failed to parse final NDJSON line:', error);
100
148
  }
101
149
  }
102
- catch (error) {
103
- throw new Error(`Failed to parse NDJSON line: ${error}`);
104
- }
150
+ }
151
+ catch (error) {
152
+ throw new Error(`NDJSON stream reading error: ${error}`);
105
153
  }
106
154
  // Return aggregated result
107
155
  return {
@@ -75,19 +75,31 @@ export class QueryClient {
75
75
  mode: options.mode,
76
76
  test_mode: options.testMode,
77
77
  },
78
+ // For streaming mode, don't parse response - get raw Response object
79
+ ...(options.mode === 'stream' ? { parseAs: 'stream' as const } : {}),
78
80
  }
79
81
 
80
- // Execute the query
81
82
  const response = await executeCypherQuery(data)
82
83
 
83
- // Check if this is an NDJSON streaming response
84
- // The SDK returns the response object which includes the raw Response
85
- if (response.response) {
84
+ // Check if this is a raw stream response (when parseAs: 'stream')
85
+ if (options.mode === 'stream' && response.response) {
86
86
  const contentType = response.response.headers.get('content-type') || ''
87
- const streamFormat = response.response.headers.get('x-stream-format')
88
87
 
89
- if (contentType.includes('application/x-ndjson') || streamFormat === 'ndjson') {
88
+ if (contentType.includes('application/x-ndjson')) {
90
89
  return this.parseNDJSONResponse(response.response, graphId)
90
+ } else if (contentType.includes('application/json')) {
91
+ // Fallback: parse JSON manually
92
+ const data = await response.response.json()
93
+ if (data.data !== undefined && data.columns) {
94
+ return {
95
+ data: data.data,
96
+ columns: data.columns,
97
+ row_count: data.row_count || data.data.length,
98
+ execution_time_ms: data.execution_time_ms || 0,
99
+ graph_id: graphId,
100
+ timestamp: data.timestamp || new Date().toISOString(),
101
+ }
102
+ }
91
103
  }
92
104
  }
93
105
 
@@ -118,11 +130,7 @@ export class QueryClient {
118
130
  }
119
131
 
120
132
  // Use SSE to monitor the operation
121
- if (options.mode === 'stream') {
122
- return this.streamQueryResults(queuedResponse.operation_id, options)
123
- } else {
124
- return this.waitForQueryCompletion(queuedResponse.operation_id, options)
125
- }
133
+ return this.waitForQueryCompletion(queuedResponse.operation_id, options)
126
134
  }
127
135
 
128
136
  // Unexpected response format
@@ -135,37 +143,77 @@ export class QueryClient {
135
143
  let totalRows = 0
136
144
  let executionTimeMs = 0
137
145
 
138
- // Parse NDJSON line by line
139
- const text = await response.text()
140
- const lines = text.trim().split('\n')
146
+ // Use streaming reader to avoid "body already read" error
147
+ const reader = response.body?.getReader()
148
+ if (!reader) {
149
+ throw new Error('Response body is not readable')
150
+ }
151
+
152
+ const decoder = new TextDecoder()
153
+ let buffer = ''
141
154
 
142
- for (const line of lines) {
143
- if (!line.trim()) continue
155
+ try {
156
+ while (true) {
157
+ const { done, value } = await reader.read()
158
+ if (done) break
144
159
 
145
- try {
146
- const chunk = JSON.parse(line)
160
+ buffer += decoder.decode(value, { stream: true })
161
+ const lines = buffer.split('\n')
162
+ buffer = lines.pop() || ''
147
163
 
148
- // Extract columns from first chunk
149
- if (columns === null && chunk.columns) {
150
- columns = chunk.columns
151
- }
164
+ for (const line of lines) {
165
+ if (!line.trim()) continue
166
+
167
+ try {
168
+ const chunk = JSON.parse(line)
152
169
 
153
- // Aggregate data rows (NDJSON uses "rows", regular JSON uses "data")
154
- if (chunk.rows) {
155
- allData.push(...chunk.rows)
156
- totalRows += chunk.rows.length
157
- } else if (chunk.data) {
158
- allData.push(...chunk.data)
159
- totalRows += chunk.data.length
170
+ // Extract columns from first chunk
171
+ if (columns === null && chunk.columns) {
172
+ columns = chunk.columns
173
+ }
174
+
175
+ // Aggregate data rows (NDJSON uses "rows", regular JSON uses "data")
176
+ if (chunk.rows) {
177
+ allData.push(...chunk.rows)
178
+ totalRows += chunk.rows.length
179
+ } else if (chunk.data) {
180
+ allData.push(...chunk.data)
181
+ totalRows += chunk.data.length
182
+ }
183
+
184
+ // Track execution time (use max from all chunks)
185
+ if (chunk.execution_time_ms) {
186
+ executionTimeMs = Math.max(executionTimeMs, chunk.execution_time_ms)
187
+ }
188
+ } catch (error) {
189
+ console.error('Failed to parse NDJSON line:', error)
190
+ }
160
191
  }
192
+ }
161
193
 
162
- // Track execution time (use max from all chunks)
163
- if (chunk.execution_time_ms) {
164
- executionTimeMs = Math.max(executionTimeMs, chunk.execution_time_ms)
194
+ // Parse any remaining buffer
195
+ if (buffer.trim()) {
196
+ try {
197
+ const chunk = JSON.parse(buffer)
198
+ if (columns === null && chunk.columns) {
199
+ columns = chunk.columns
200
+ }
201
+ if (chunk.rows) {
202
+ allData.push(...chunk.rows)
203
+ totalRows += chunk.rows.length
204
+ } else if (chunk.data) {
205
+ allData.push(...chunk.data)
206
+ totalRows += chunk.data.length
207
+ }
208
+ if (chunk.execution_time_ms) {
209
+ executionTimeMs = Math.max(executionTimeMs, chunk.execution_time_ms)
210
+ }
211
+ } catch (error) {
212
+ console.error('Failed to parse final NDJSON line:', error)
165
213
  }
166
- } catch (error) {
167
- throw new Error(`Failed to parse NDJSON line: ${error}`)
168
214
  }
215
+ } catch (error) {
216
+ throw new Error(`NDJSON stream reading error: ${error}`)
169
217
  }
170
218
 
171
219
  // Return aggregated result
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { OperationClient } from './OperationClient';
6
6
  import { QueryClient } from './QueryClient';
7
+ import { AgentClient } from './AgentClient';
7
8
  import { SSEClient } from './SSEClient';
8
9
  import { TableIngestClient } from './TableIngestClient';
9
10
  import { GraphClient } from './GraphClient';
@@ -17,6 +18,7 @@ export interface RoboSystemsExtensionConfig {
17
18
  }
18
19
  export declare class RoboSystemsExtensions {
19
20
  readonly query: QueryClient;
21
+ readonly agent: AgentClient;
20
22
  readonly operations: OperationClient;
21
23
  readonly tables: TableIngestClient;
22
24
  readonly graphs: GraphClient;
@@ -37,13 +39,15 @@ export declare class RoboSystemsExtensions {
37
39
  }
38
40
  export * from './OperationClient';
39
41
  export * from './QueryClient';
42
+ export * from './AgentClient';
40
43
  export * from './SSEClient';
41
44
  export * from './TableIngestClient';
42
45
  export * from './GraphClient';
43
- export { OperationClient, QueryClient, SSEClient, TableIngestClient, GraphClient };
46
+ export { OperationClient, QueryClient, AgentClient, SSEClient, TableIngestClient, GraphClient };
44
47
  export { useMultipleOperations, useOperation, useQuery, useSDKClients, useStreamingQuery, useTableUpload, } from './hooks';
45
48
  export declare const extensions: {
46
49
  readonly query: QueryClient;
50
+ readonly agent: AgentClient;
47
51
  readonly operations: OperationClient;
48
52
  readonly graphs: GraphClient;
49
53
  monitorOperation: (operationId: string, onProgress?: (progress: any) => void) => Promise<any>;
@@ -53,3 +57,5 @@ export declare const extensions: {
53
57
  export declare const monitorOperation: (operationId: string, onProgress?: (progress: any) => void) => Promise<any>;
54
58
  export declare const executeQuery: (graphId: string, query: string, parameters?: Record<string, any>) => Promise<import("./QueryClient").QueryResult>;
55
59
  export declare const streamQuery: (graphId: string, query: string, parameters?: Record<string, any>, chunkSize?: number) => AsyncIterableIterator<any>;
60
+ export declare const agentQuery: (graphId: string, message: string, context?: Record<string, any>) => Promise<import("./AgentClient").AgentResult>;
61
+ export declare const analyzeFinancials: (graphId: string, message: string) => Promise<import("./AgentClient").AgentResult>;
@@ -18,13 +18,15 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
18
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.streamQuery = exports.executeQuery = exports.monitorOperation = exports.extensions = exports.useTableUpload = exports.useStreamingQuery = exports.useSDKClients = exports.useQuery = exports.useOperation = exports.useMultipleOperations = exports.GraphClient = exports.TableIngestClient = exports.SSEClient = exports.QueryClient = exports.OperationClient = exports.RoboSystemsExtensions = void 0;
21
+ exports.analyzeFinancials = exports.agentQuery = exports.streamQuery = exports.executeQuery = exports.monitorOperation = exports.extensions = exports.useTableUpload = exports.useStreamingQuery = exports.useSDKClients = exports.useQuery = exports.useOperation = exports.useMultipleOperations = exports.GraphClient = exports.TableIngestClient = exports.SSEClient = exports.AgentClient = exports.QueryClient = exports.OperationClient = exports.RoboSystemsExtensions = void 0;
22
22
  const client_gen_1 = require("../client.gen");
23
23
  const config_1 = require("./config");
24
24
  const OperationClient_1 = require("./OperationClient");
25
25
  Object.defineProperty(exports, "OperationClient", { enumerable: true, get: function () { return OperationClient_1.OperationClient; } });
26
26
  const QueryClient_1 = require("./QueryClient");
27
27
  Object.defineProperty(exports, "QueryClient", { enumerable: true, get: function () { return QueryClient_1.QueryClient; } });
28
+ const AgentClient_1 = require("./AgentClient");
29
+ Object.defineProperty(exports, "AgentClient", { enumerable: true, get: function () { return AgentClient_1.AgentClient; } });
28
30
  const SSEClient_1 = require("./SSEClient");
29
31
  Object.defineProperty(exports, "SSEClient", { enumerable: true, get: function () { return SSEClient_1.SSEClient; } });
30
32
  const TableIngestClient_1 = require("./TableIngestClient");
@@ -51,6 +53,12 @@ class RoboSystemsExtensions {
51
53
  token: this.config.token,
52
54
  headers: this.config.headers,
53
55
  });
56
+ this.agent = new AgentClient_1.AgentClient({
57
+ baseUrl: this.config.baseUrl,
58
+ credentials: this.config.credentials,
59
+ token: this.config.token,
60
+ headers: this.config.headers,
61
+ });
54
62
  this.operations = new OperationClient_1.OperationClient({
55
63
  baseUrl: this.config.baseUrl,
56
64
  credentials: this.config.credentials,
@@ -95,6 +103,7 @@ class RoboSystemsExtensions {
95
103
  */
96
104
  close() {
97
105
  this.query.close();
106
+ this.agent.close();
98
107
  this.operations.closeAll();
99
108
  this.graphs.close();
100
109
  }
@@ -103,6 +112,7 @@ exports.RoboSystemsExtensions = RoboSystemsExtensions;
103
112
  // Export all types and classes
104
113
  __exportStar(require("./OperationClient"), exports);
105
114
  __exportStar(require("./QueryClient"), exports);
115
+ __exportStar(require("./AgentClient"), exports);
106
116
  __exportStar(require("./SSEClient"), exports);
107
117
  __exportStar(require("./TableIngestClient"), exports);
108
118
  __exportStar(require("./GraphClient"), exports);
@@ -126,6 +136,9 @@ exports.extensions = {
126
136
  get query() {
127
137
  return getExtensions().query;
128
138
  },
139
+ get agent() {
140
+ return getExtensions().agent;
141
+ },
129
142
  get operations() {
130
143
  return getExtensions().operations;
131
144
  },
@@ -143,3 +156,7 @@ const executeQuery = (graphId, query, parameters) => getExtensions().query.query
143
156
  exports.executeQuery = executeQuery;
144
157
  const streamQuery = (graphId, query, parameters, chunkSize) => getExtensions().query.streamQuery(graphId, query, parameters, chunkSize);
145
158
  exports.streamQuery = streamQuery;
159
+ const agentQuery = (graphId, message, context) => getExtensions().agent.query(graphId, message, context);
160
+ exports.agentQuery = agentQuery;
161
+ const analyzeFinancials = (graphId, message) => getExtensions().agent.analyzeFinancials(graphId, message);
162
+ exports.analyzeFinancials = analyzeFinancials;
@@ -7,6 +7,7 @@ import { client } from '../client.gen'
7
7
  import { extractTokenFromSDKClient } from './config'
8
8
  import { OperationClient } from './OperationClient'
9
9
  import { QueryClient } from './QueryClient'
10
+ import { AgentClient } from './AgentClient'
10
11
  import { SSEClient } from './SSEClient'
11
12
  import { TableIngestClient } from './TableIngestClient'
12
13
  import { GraphClient } from './GraphClient'
@@ -32,6 +33,7 @@ interface ResolvedConfig {
32
33
 
33
34
  export class RoboSystemsExtensions {
34
35
  public readonly query: QueryClient
36
+ public readonly agent: AgentClient
35
37
  public readonly operations: OperationClient
36
38
  public readonly tables: TableIngestClient
37
39
  public readonly graphs: GraphClient
@@ -60,6 +62,13 @@ export class RoboSystemsExtensions {
60
62
  headers: this.config.headers,
61
63
  })
62
64
 
65
+ this.agent = new AgentClient({
66
+ baseUrl: this.config.baseUrl,
67
+ credentials: this.config.credentials,
68
+ token: this.config.token,
69
+ headers: this.config.headers,
70
+ })
71
+
63
72
  this.operations = new OperationClient({
64
73
  baseUrl: this.config.baseUrl,
65
74
  credentials: this.config.credentials,
@@ -109,6 +118,7 @@ export class RoboSystemsExtensions {
109
118
  */
110
119
  close(): void {
111
120
  this.query.close()
121
+ this.agent.close()
112
122
  this.operations.closeAll()
113
123
  this.graphs.close()
114
124
  }
@@ -117,10 +127,11 @@ export class RoboSystemsExtensions {
117
127
  // Export all types and classes
118
128
  export * from './OperationClient'
119
129
  export * from './QueryClient'
130
+ export * from './AgentClient'
120
131
  export * from './SSEClient'
121
132
  export * from './TableIngestClient'
122
133
  export * from './GraphClient'
123
- export { OperationClient, QueryClient, SSEClient, TableIngestClient, GraphClient }
134
+ export { OperationClient, QueryClient, AgentClient, SSEClient, TableIngestClient, GraphClient }
124
135
 
125
136
  // Export React hooks
126
137
  export {
@@ -146,6 +157,9 @@ export const extensions = {
146
157
  get query() {
147
158
  return getExtensions().query
148
159
  },
160
+ get agent() {
161
+ return getExtensions().agent
162
+ },
149
163
  get operations() {
150
164
  return getExtensions().operations
151
165
  },
@@ -171,3 +185,9 @@ export const streamQuery = (
171
185
  parameters?: Record<string, any>,
172
186
  chunkSize?: number
173
187
  ) => getExtensions().query.streamQuery(graphId, query, parameters, chunkSize)
188
+
189
+ export const agentQuery = (graphId: string, message: string, context?: Record<string, any>) =>
190
+ getExtensions().agent.query(graphId, message, context)
191
+
192
+ export const analyzeFinancials = (graphId: string, message: string) =>
193
+ getExtensions().agent.analyzeFinancials(graphId, message)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robosystems/client",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "TypeScript client library for RoboSystems Financial Knowledge Graph API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",