@robosystems/client 0.1.10

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Harbinger FinLab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,455 @@
1
+ # RoboSystems TypeScript Client
2
+
3
+ [![npm version](https://badge.fury.io/js/@robosystems%2Fclient.svg)](https://www.npmjs.com/package/@robosystems/client)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Official TypeScript Client for the RoboSystems Financial Knowledge Graph API. Access comprehensive financial data including accounting records, SEC filings, and advanced graph analytics through a type-safe, modern TypeScript interface.
7
+
8
+ ## Features
9
+
10
+ - **Type-safe API client** with full TypeScript types
11
+ - **Auto-generated from OpenAPI** for always up-to-date types
12
+ - **Browser & Node.js support** with different auth strategies
13
+ - **React hooks** for seamless UI integration
14
+ - **Queue handling** for long-running operations
15
+ - **Streaming support** for large datasets
16
+ - **Financial AI Agent** integration
17
+ - **Comprehensive error handling** with typed errors
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install @robosystems/client
23
+ # or
24
+ yarn add @robosystems/client
25
+ # or
26
+ pnpm add @robosystems/client
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ ### Browser Usage (with cookies)
32
+
33
+ ```typescript
34
+ import { client, getUserMe, listCompanies, executeCypherQuery } from '@robosystems/client'
35
+
36
+ // Configure the client
37
+ client.setConfig({
38
+ baseUrl: 'https://api.robosystems.ai',
39
+ credentials: 'include',
40
+ })
41
+
42
+ // Use with cookie-based authentication (browser)
43
+ const { data: user, error } = await getCurrentUser()
44
+ if (user) {
45
+ console.log('Logged in as:', user.email)
46
+ }
47
+
48
+ // List companies in a graph
49
+ const { data: companies } = await listCompanies({
50
+ path: { graph_id: 'your-graph-id' },
51
+ query: { limit: 10 },
52
+ })
53
+
54
+ // Execute a Cypher query
55
+ const { data: result } = await executeCypherQuery({
56
+ path: { graph_id: 'your-graph-id' },
57
+ body: {
58
+ query: 'MATCH (c:Company)-[:HAS_FILING]->(f:Filing) RETURN c.name, f.form_type LIMIT 5',
59
+ },
60
+ })
61
+ ```
62
+
63
+ ### Server Usage (with API key)
64
+
65
+ ```typescript
66
+ import { client, getUserGraphs, listCompanies } from '@robosystems/client'
67
+
68
+ // Configure with API key for server-side usage
69
+ client.setConfig({
70
+ baseUrl: 'https://api.robosystems.ai',
71
+ headers: {
72
+ 'X-API-Key': process.env.ROBOSYSTEMS_API_KEY!,
73
+ },
74
+ })
75
+
76
+ // Fetch user's graphs
77
+ const { data: graphs, error } = await getUserGraphs()
78
+
79
+ // Work with financial data
80
+ if (graphs?.graphs.length) {
81
+ const graphId = graphs.graphs[0].graph_id
82
+ const { data: companies } = await listCompanies({
83
+ path: { graph_id: graphId },
84
+ })
85
+ }
86
+ ```
87
+
88
+ ## Key API Endpoints
89
+
90
+ ### Authentication & User Management
91
+
92
+ ```typescript
93
+ import {
94
+ registerUser,
95
+ loginUser,
96
+ logoutUser,
97
+ getCurrentUser,
98
+ createUserApiKey,
99
+ } from '@robosystems/client'
100
+
101
+ // Register a new user
102
+ const { data, error } = await registerUser({
103
+ body: {
104
+ email: 'user@example.com',
105
+ password: 'secure-password',
106
+ name: 'John Doe',
107
+ },
108
+ })
109
+
110
+ // Sign in
111
+ const { data: session } = await loginUser({
112
+ body: {
113
+ username: 'user@example.com',
114
+ password: 'secure-password',
115
+ },
116
+ })
117
+
118
+ // Get current user
119
+ const { data: user } = await getCurrentUser()
120
+
121
+ // Create API key for programmatic access
122
+ const { data: apiKey } = await createUserApiKey({
123
+ body: {
124
+ key_name: 'Production Server',
125
+ key_type: 'user',
126
+ },
127
+ })
128
+ console.log('Save this key securely:', apiKey.key)
129
+
130
+ // Sign out
131
+ await logoutUser()
132
+ ```
133
+
134
+ ### Company & Financial Data
135
+
136
+ ```typescript
137
+ import {
138
+ listCompanies,
139
+ getCompany,
140
+ createCompany,
141
+ createConnection,
142
+ syncConnection,
143
+ } from '@robosystems/client'
144
+
145
+ // List companies with pagination
146
+ const { data: companies } = await listCompanies({
147
+ path: { graph_id: 'your-graph-id' },
148
+ query: { limit: 20, offset: 0 },
149
+ })
150
+ console.log(`Found ${companies.total} companies`)
151
+
152
+ // Get specific company details
153
+ const { data: company } = await getCompany({
154
+ path: {
155
+ graph_id: 'your-graph-id',
156
+ company_id: 'AAPL',
157
+ },
158
+ })
159
+
160
+ // Create new company
161
+ const { data: newCompany } = await createCompany({
162
+ path: { graph_id: 'your-graph-id' },
163
+ body: {
164
+ identifier: 'MSFT',
165
+ name: 'Microsoft Corporation',
166
+ metadata: { industry: 'Technology' },
167
+ },
168
+ })
169
+
170
+ // Create data connection (QuickBooks, etc.)
171
+ const { data: connection } = await createConnection({
172
+ path: { graph_id: 'your-graph-id' },
173
+ body: {
174
+ name: 'QuickBooks Integration',
175
+ connection_type: 'quickbooks',
176
+ config: { company_id: '123456' },
177
+ },
178
+ })
179
+
180
+ // Sync data from connection
181
+ const { data: syncResult } = await syncConnection({
182
+ path: {
183
+ graph_id: 'your-graph-id',
184
+ connection_id: connection.id,
185
+ },
186
+ })
187
+ ```
188
+
189
+ ### Graph Queries & Analytics
190
+
191
+ ```typescript
192
+ import {
193
+ executeCypherQuery,
194
+ executeReadOnlyCypherQuery,
195
+ getGraphMetrics,
196
+ } from '@robosystems/client'
197
+
198
+ // Execute parameterized Cypher queries
199
+ const { data: results } = await executeCypherQuery({
200
+ path: { graph_id: 'your-graph-id' },
201
+ body: {
202
+ query: `
203
+ MATCH (c:Company {ticker: $ticker})-[:HAS_METRIC]->(m:Metric)
204
+ WHERE m.fiscal_year >= $start_year
205
+ RETURN m.name, m.value, m.fiscal_year
206
+ ORDER BY m.fiscal_year DESC
207
+ `,
208
+ parameters: { ticker: 'AAPL', start_year: 2020 },
209
+ },
210
+ })
211
+
212
+ // Read-only queries for better performance
213
+ const { data: readOnlyResult } = await executeReadOnlyCypherQuery({
214
+ path: { graph_id: 'your-graph-id' },
215
+ body: { query: 'MATCH (n) RETURN count(n) as total' },
216
+ })
217
+
218
+ // Get graph analytics
219
+ const { data: metrics } = await getGraphMetrics({
220
+ path: { graph_id: 'your-graph-id' },
221
+ })
222
+ console.log(`Total nodes: ${metrics.total_nodes}`)
223
+ console.log(`Total relationships: ${metrics.total_relationships}`)
224
+ ```
225
+
226
+ ### Financial AI Agent
227
+
228
+ ```typescript
229
+ import { queryFinancialAgent } from '@robosystems/client'
230
+
231
+ // Natural language financial queries
232
+ const { data: agentResponse } = await queryFinancialAgent({
233
+ path: { graph_id: 'your-graph-id' },
234
+ body: {
235
+ query: "What was Apple's revenue growth over the last 3 years?",
236
+ include_reasoning: true,
237
+ max_tokens: 1000,
238
+ },
239
+ })
240
+
241
+ console.log('Answer:', agentResponse.answer)
242
+ if (agentResponse.reasoning) {
243
+ console.log('Reasoning:', agentResponse.reasoning)
244
+ }
245
+ ```
246
+
247
+ ## Advanced Features
248
+
249
+ ### Billing & Credit Management
250
+
251
+ ```typescript
252
+ import { getCreditSummary, checkCreditBalance, getCurrentGraphBill } from '@robosystems/client'
253
+
254
+ // Monitor credits and usage for a specific graph
255
+ const { data: creditSummary } = await getCreditSummary({
256
+ path: { graph_id: 'your-graph-id' },
257
+ })
258
+ console.log(`Available credits: ${creditSummary.available_credits.toLocaleString()}`)
259
+ console.log(
260
+ `Monthly usage: ${creditSummary.used_credits.toLocaleString()}/${creditSummary.total_credits.toLocaleString()}`
261
+ )
262
+
263
+ // Check credit requirements before operations
264
+ const { data: creditCheck } = await checkCreditBalance({
265
+ path: { graph_id: 'your-graph-id' },
266
+ body: {
267
+ operation_type: 'query',
268
+ estimated_credits: 100,
269
+ },
270
+ })
271
+
272
+ if (creditCheck.has_sufficient_credits) {
273
+ // Proceed with operation
274
+ }
275
+
276
+ // Get billing information
277
+ const { data: currentBill } = await getCurrentGraphBill({
278
+ path: { graph_id: 'your-graph-id' },
279
+ })
280
+ ```
281
+
282
+ ### MCP Tools Integration
283
+
284
+ ```typescript
285
+ import { listMcpTools, callMcpTool } from '@robosystems/client'
286
+
287
+ // List available MCP tools
288
+ const { data: tools } = await listMcpTools({
289
+ path: { graph_id: 'your-graph-id' },
290
+ })
291
+ tools.tools.forEach((tool) => {
292
+ console.log(`${tool.name}: ${tool.description}`)
293
+ })
294
+
295
+ // Call an MCP tool
296
+ const { data: toolResult } = await callMcpTool({
297
+ path: { graph_id: 'your-graph-id' },
298
+ body: {
299
+ name: 'analyze_financial_statement',
300
+ arguments: {
301
+ company_id: 'AAPL',
302
+ statement_type: 'income',
303
+ fiscal_year: 2023,
304
+ },
305
+ },
306
+ })
307
+ console.log('Analysis result:', toolResult.content)
308
+ ```
309
+
310
+ ## Advanced Features
311
+
312
+ ### Error Handling
313
+
314
+ ```typescript
315
+ import { listCompanies } from '@robosystems/client'
316
+ import type { ErrorResponse } from '@robosystems/client'
317
+
318
+ try {
319
+ const { data, error } = await listCompanies({
320
+ path: { graph_id: 'your-graph-id' },
321
+ })
322
+
323
+ if (error) {
324
+ const apiError = error as ErrorResponse
325
+
326
+ switch (apiError.status) {
327
+ case 400:
328
+ console.error('Validation error:', apiError.detail)
329
+ break
330
+ case 401:
331
+ console.error('Authentication failed - check your API key')
332
+ break
333
+ case 403:
334
+ console.error('Permission denied - check graph access')
335
+ break
336
+ case 429:
337
+ console.error('Rate limit exceeded - retry later')
338
+ break
339
+ case 503:
340
+ console.error('Service temporarily unavailable')
341
+ break
342
+ default:
343
+ console.error('API Error:', apiError.detail || apiError.message)
344
+ }
345
+ } else if (data) {
346
+ console.log(`Found ${data.total} companies`)
347
+ }
348
+ } catch (err) {
349
+ // Network errors
350
+ console.error('Network Error:', err)
351
+ }
352
+ ```
353
+
354
+ ### TypeScript Types
355
+
356
+ All API responses and requests are fully typed:
357
+
358
+ ```typescript
359
+ import type {
360
+ User,
361
+ Graph,
362
+ Company,
363
+ CompanyCreate,
364
+ CypherQueryRequest,
365
+ CypherQueryResponse,
366
+ AgentQueryRequest,
367
+ AgentQueryResponse,
368
+ ErrorResponse,
369
+ PaginatedResponse,
370
+ } from '@robosystems/client'
371
+
372
+ // Type-safe function example
373
+ function processCompany(company: Company): void {
374
+ console.log(`Company: ${company.name} (${company.identifier})`)
375
+ if (company.metadata) {
376
+ console.log('Industry:', company.metadata.industry)
377
+ }
378
+ }
379
+
380
+ // Type-safe query builder
381
+ function buildMetricQuery(ticker: string, startYear: number): CypherQueryRequest {
382
+ return {
383
+ query: `
384
+ MATCH (c:Company {ticker: $ticker})-[:HAS_METRIC]->(m:Metric)
385
+ WHERE m.fiscal_year >= $start_year
386
+ RETURN m
387
+ `,
388
+ parameters: { ticker, start_year: startYear },
389
+ }
390
+ }
391
+ ```
392
+
393
+ ## Environment Configuration
394
+
395
+ ### Next.js App Router
396
+
397
+ ```typescript
398
+ // app/api/robosystems/route.ts
399
+ import { client } from '@robosystems/client'
400
+
401
+ // Configure for server-side API routes
402
+ client.setConfig({
403
+ baseUrl: process.env.ROBOSYSTEMS_API_URL || 'https://api.robosystems.ai',
404
+ headers: {
405
+ 'X-API-Key': process.env.ROBOSYSTEMS_API_KEY!,
406
+ },
407
+ })
408
+ ```
409
+
410
+ ### React SPA
411
+
412
+ ```typescript
413
+ // src/lib/robosystems.ts
414
+ import { client } from '@robosystems/client'
415
+
416
+ // Configure for browser with cookies
417
+ client.setConfig({
418
+ baseUrl: import.meta.env.VITE_ROBOSYSTEMS_API_URL || 'https://api.robosystems.ai',
419
+ credentials: 'include',
420
+ })
421
+ ```
422
+
423
+ ### Node.js Script
424
+
425
+ ```typescript
426
+ // scripts/analyze.ts
427
+ import { client } from '@robosystems/client'
428
+ import dotenv from 'dotenv'
429
+
430
+ dotenv.config()
431
+
432
+ client.setConfig({
433
+ baseUrl: process.env.ROBOSYSTEMS_API_URL || 'https://api.robosystems.ai',
434
+ headers: {
435
+ 'X-API-Key': process.env.ROBOSYSTEMS_API_KEY!,
436
+ },
437
+ })
438
+ ```
439
+
440
+ ## API Reference
441
+
442
+ - Full API documentation: [https://api.robosystems.ai/docs](https://api.robosystems.ai/docs)
443
+ - OpenAPI specification: [https://api.robosystems.ai/openapi.json](https://api.robosystems.ai/openapi.json)
444
+
445
+ ## Support
446
+
447
+ - Documentation: [https://docs.robosystems.ai](https://docs.robosystems.ai)
448
+ - Issues: [GitHub Issues](https://github.com/HarbingerFinLab/robosystems-typescript-client/issues)
449
+ - Email: support@robosystems.ai
450
+
451
+ ## License
452
+
453
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
454
+
455
+ MIT © 2024 Harbinger FinLab
@@ -0,0 +1,200 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+ /* eslint-disable no-undef */
3
+
4
+ import type { Client, Config, ResolvedRequestOptions } from './types.gen';
5
+ import {
6
+ buildUrl,
7
+ createConfig,
8
+ createInterceptors,
9
+ getParseAs,
10
+ mergeConfigs,
11
+ mergeHeaders,
12
+ setAuthParams,
13
+ } from './utils.gen';
14
+
15
+ type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
16
+ body?: any;
17
+ headers: ReturnType<typeof mergeHeaders>;
18
+ };
19
+
20
+ export const createClient = (config: Config = {}): Client => {
21
+ let _config = mergeConfigs(createConfig(), config);
22
+
23
+ const getConfig = (): Config => ({ ..._config });
24
+
25
+ const setConfig = (config: Config): Config => {
26
+ _config = mergeConfigs(_config, config);
27
+ return getConfig();
28
+ };
29
+
30
+ const interceptors = createInterceptors<
31
+ Request,
32
+ Response,
33
+ unknown,
34
+ ResolvedRequestOptions
35
+ >();
36
+
37
+ const request: Client['request'] = async (options) => {
38
+ const opts = {
39
+ ..._config,
40
+ ...options,
41
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
42
+ headers: mergeHeaders(_config.headers, options.headers),
43
+ serializedBody: undefined,
44
+ };
45
+
46
+ if (opts.security) {
47
+ await setAuthParams({
48
+ ...opts,
49
+ security: opts.security,
50
+ });
51
+ }
52
+
53
+ if (opts.requestValidator) {
54
+ await opts.requestValidator(opts);
55
+ }
56
+
57
+ if (opts.body && opts.bodySerializer) {
58
+ opts.serializedBody = opts.bodySerializer(opts.body);
59
+ }
60
+
61
+ // remove Content-Type header if body is empty to avoid sending invalid requests
62
+ if (opts.serializedBody === undefined || opts.serializedBody === '') {
63
+ opts.headers.delete('Content-Type');
64
+ }
65
+
66
+ const url = buildUrl(opts);
67
+ const requestInit: ReqInit = {
68
+ redirect: 'follow',
69
+ ...opts,
70
+ body: opts.serializedBody,
71
+ };
72
+
73
+ let request = new Request(url, requestInit);
74
+
75
+ for (const fn of interceptors.request._fns) {
76
+ if (fn) {
77
+ request = await fn(request, opts);
78
+ }
79
+ }
80
+
81
+ // fetch must be assigned here, otherwise it would throw the error:
82
+ // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
83
+ const _fetch = opts.fetch!;
84
+ let response = await _fetch(request);
85
+
86
+ for (const fn of interceptors.response._fns) {
87
+ if (fn) {
88
+ response = await fn(response, request, opts);
89
+ }
90
+ }
91
+
92
+ const result = {
93
+ request,
94
+ response,
95
+ };
96
+
97
+ if (response.ok) {
98
+ if (
99
+ response.status === 204 ||
100
+ response.headers.get('Content-Length') === '0'
101
+ ) {
102
+ return opts.responseStyle === 'data'
103
+ ? {}
104
+ : {
105
+ data: {},
106
+ ...result,
107
+ };
108
+ }
109
+
110
+ const parseAs =
111
+ (opts.parseAs === 'auto'
112
+ ? getParseAs(response.headers.get('Content-Type'))
113
+ : opts.parseAs) ?? 'json';
114
+
115
+ let data: any;
116
+ switch (parseAs) {
117
+ case 'arrayBuffer':
118
+ case 'blob':
119
+ case 'formData':
120
+ case 'json':
121
+ case 'text':
122
+ data = await response[parseAs]();
123
+ break;
124
+ case 'stream':
125
+ return opts.responseStyle === 'data'
126
+ ? response.body
127
+ : {
128
+ data: response.body,
129
+ ...result,
130
+ };
131
+ }
132
+
133
+ if (parseAs === 'json') {
134
+ if (opts.responseValidator) {
135
+ await opts.responseValidator(data);
136
+ }
137
+
138
+ if (opts.responseTransformer) {
139
+ data = await opts.responseTransformer(data);
140
+ }
141
+ }
142
+
143
+ return opts.responseStyle === 'data'
144
+ ? data
145
+ : {
146
+ data,
147
+ ...result,
148
+ };
149
+ }
150
+
151
+ const textError = await response.text();
152
+ let jsonError: unknown;
153
+
154
+ try {
155
+ jsonError = JSON.parse(textError);
156
+ } catch {
157
+ // noop
158
+ }
159
+
160
+ const error = jsonError ?? textError;
161
+ let finalError = error;
162
+
163
+ for (const fn of interceptors.error._fns) {
164
+ if (fn) {
165
+ finalError = (await fn(error, response, request, opts)) as string;
166
+ }
167
+ }
168
+
169
+ finalError = finalError || ({} as string);
170
+
171
+ if (opts.throwOnError) {
172
+ throw finalError;
173
+ }
174
+
175
+ // TODO: we probably want to return error and improve types
176
+ return opts.responseStyle === 'data'
177
+ ? undefined
178
+ : {
179
+ error: finalError,
180
+ ...result,
181
+ };
182
+ };
183
+
184
+ return {
185
+ buildUrl,
186
+ connect: (options) => request({ ...options, method: 'CONNECT' }),
187
+ delete: (options) => request({ ...options, method: 'DELETE' }),
188
+ get: (options) => request({ ...options, method: 'GET' }),
189
+ getConfig,
190
+ head: (options) => request({ ...options, method: 'HEAD' }),
191
+ interceptors,
192
+ options: (options) => request({ ...options, method: 'OPTIONS' }),
193
+ patch: (options) => request({ ...options, method: 'PATCH' }),
194
+ post: (options) => request({ ...options, method: 'POST' }),
195
+ put: (options) => request({ ...options, method: 'PUT' }),
196
+ request,
197
+ setConfig,
198
+ trace: (options) => request({ ...options, method: 'TRACE' }),
199
+ };
200
+ };
@@ -0,0 +1,25 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ export type { Auth } from '../core/auth.gen';
4
+ export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
5
+ export {
6
+ formDataBodySerializer,
7
+ jsonBodySerializer,
8
+ urlSearchParamsBodySerializer,
9
+ } from '../core/bodySerializer.gen';
10
+ export { buildClientParams } from '../core/params.gen';
11
+ export { createClient } from './client.gen';
12
+ export type {
13
+ Client,
14
+ ClientOptions,
15
+ Config,
16
+ CreateClientConfig,
17
+ Options,
18
+ OptionsLegacyParser,
19
+ RequestOptions,
20
+ RequestResult,
21
+ ResolvedRequestOptions,
22
+ ResponseStyle,
23
+ TDataShape,
24
+ } from './types.gen';
25
+ export { createConfig, mergeHeaders } from './utils.gen';