@railtownai/railengine 0.0.3 → 0.0.5

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 CHANGED
@@ -1,570 +1,208 @@
1
- # @railtownai/railengine
2
-
3
- JavaScript/TypeScript SDK for Railtown AI Rail Engine - Retrieval package. This package provides a simple interface for reading and searching data from Rail Engine.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @railtownai/railengine
9
- ```
10
-
11
- ## Requirements
12
-
13
- - Node.js 20+
14
- - TypeScript 5.0+ (optional, but recommended)
15
-
16
- ## Quick Start
17
-
18
- ### Basic Usage
19
-
20
- ```typescript
21
- import { RailEngine } from "@railtownai/railengine";
22
-
23
- // Initialize client
24
- const client = new RailEngine({
25
- pat: "your-pat-token",
26
- engineId: "your-engine-id"
27
- });
28
-
29
- // Search vector store
30
- const results = client.searchVectorStore("engine-id", "VectorStore1", "search query");
31
- for await (const result of results) {
32
- console.log(result);
33
- }
34
-
35
- // Get storage document by EventId
36
- const document = await client.getStorageDocumentByEventId("engine-id", "event-id");
37
- console.log(document);
38
- ```
39
-
40
- ### Using Environment Variables
41
-
42
- ```typescript
43
- import { RailEngine } from "@railtownai/railengine";
44
-
45
- // ENGINE_PAT and ENGINE_ID are read from environment variables automatically
46
- const client = new RailEngine();
47
-
48
- // Use client.engineId if you need it
49
- const results = client.searchVectorStore(client.engineId, "VectorStore1", "query");
50
- for await (const result of results) {
51
- console.log(result);
52
- }
53
- ```
54
-
55
- ## Authentication Configuration
56
-
57
- The retrieval package uses PAT (Personal Access Token) for authentication.
58
-
59
- ### Environment Variables
60
-
61
- - `ENGINE_PAT` - Personal Access Token (required)
62
- - `ENGINE_ID` - Engine ID (optional, but required if not provided via constructor)
63
- - `RAILTOWN_API_URL` - Base API URL (optional, defaults to `https://cndr.railtown.ai/api`)
64
-
65
- ### Setting Environment Variables
66
-
67
- #### Windows (PowerShell)
68
-
69
- ```powershell
70
- $env:ENGINE_PAT="<your-pat-token>"
71
- $env:ENGINE_ID="<your-engine-id>"
72
- $env:RAILTOWN_API_URL="https://cndr.railtown.ai/api" # Optional
73
- ```
74
-
75
- #### Windows (Command Prompt)
76
-
77
- ```cmd
78
- set ENGINE_PAT=<your-pat-token>
79
- set ENGINE_ID=<your-engine-id>
80
- set RAILTOWN_API_URL=https://cndr.railtown.ai/api
81
- ```
82
-
83
- #### macOS/Linux
84
-
85
- ```bash
86
- export ENGINE_PAT="<your-pat-token>"
87
- export ENGINE_ID="<your-engine-id>"
88
- export RAILTOWN_API_URL="https://cndr.railtown.ai/api" # Optional
89
- ```
90
-
91
- #### .env file
92
-
93
- Create a `.env` file in your project root:
94
-
95
- ```
96
- ENGINE_PAT=<your-pat-token>
97
- ENGINE_ID=<your-engine-id>
98
- RAILTOWN_API_URL=https://cndr.railtown.ai/api
99
- ```
100
-
101
- Then use a package like `dotenv` to load it:
102
-
103
- ```typescript
104
- import "dotenv/config";
105
- import { RailEngine } from "@railtownai/railengine";
106
-
107
- const client = new RailEngine(); // Reads from environment variables
108
- ```
109
-
110
- ### Configuration Priority
111
-
112
- 1. Constructor parameters (highest priority)
113
- 2. Environment variables
114
- 3. Default values (where applicable)
115
-
116
- **Note**: If `ENGINE_ID` is set in environment variables, you don't need to specify it in client initialization. If `ENGINE_ID` is NOT set in environment variables, you MUST specify it in client initialization.
117
-
118
- ## Zod Schema Support
119
-
120
- You can provide a Zod schema during client initialization to automatically validate retrieved data:
121
-
122
- ```typescript
123
- import { z } from "zod";
124
- import { RailEngine } from "@railtownai/railengine";
125
-
126
- const FoodDiaryItemSchema = z.object({
127
- food_name: z.string(),
128
- calories: z.number(),
129
- carbs: z.number(),
130
- proteins: z.number(),
131
- fats: z.number()
132
- });
133
-
134
- type FoodDiaryItem = z.infer<typeof FoodDiaryItemSchema>;
135
-
136
- // Initialize with schema
137
- const client = new RailEngine({
138
- pat: "your-pat-token",
139
- engineId: "your-engine-id",
140
- schema: FoodDiaryItemSchema
141
- });
142
-
143
- // Results automatically validated against FoodDiaryItemSchema
144
- const results = client.searchVectorStore("engine-id", "VectorStore1", "apple");
145
- for await (const item of results) {
146
- // item is FoodDiaryItem
147
- console.log(item.food_name, item.calories);
148
- }
149
- ```
150
-
151
- ### Overriding Schema Per Call
152
-
153
- You can override the default schema on individual method calls:
154
-
155
- ```typescript
156
- const FoodSummarySchema = z.object({
157
- name: z.string(),
158
- cal: z.number()
159
- });
160
-
161
- const results = client.searchVectorStore("engine-id", "VectorStore1", "apple", {
162
- schema: FoodSummarySchema // Override default schema
163
- });
164
- ```
165
-
166
- ## Client-Side Filtering
167
-
168
- All retrieval methods support optional client-side filtering via `filterFn`:
169
-
170
- ```typescript
171
- // Filter results by CustomerKey pattern
172
- const results = client.searchVectorStore("engine-id", "VectorStore1", "query", {
173
- filterFn: (item) => {
174
- const customerKey = (item as { CustomerKey?: string }).CustomerKey || "";
175
- return customerKey.startsWith("doc-");
176
- }
177
- });
178
-
179
- for await (const result of results) {
180
- console.log(result);
181
- }
182
- ```
183
-
184
- ### Filtering with Pagination
185
-
186
- Filtering works seamlessly with pagination - filters are applied across all pages automatically:
187
-
188
- ```typescript
189
- // List documents and filter by version
190
- const documents = client.listStorageDocuments("engine-id", {
191
- filterFn: (doc) => ((doc as { Version?: number }).Version || 0) > 1
192
- });
193
-
194
- for await (const doc of documents) {
195
- console.log(doc);
196
- }
197
- ```
198
-
199
- ## API Methods
200
-
201
- ### Embeddings API
202
-
203
- #### searchVectorStore
204
-
205
- Search a vector store using semantic similarity.
206
-
207
- ```typescript
208
- const results = client.searchVectorStore(
209
- engineId: string,
210
- vectorStore: string,
211
- query: string,
212
- options?: {
213
- filterFn?: (item: T | Record<string, unknown>) => boolean;
214
- schema?: z.ZodSchema<unknown>;
215
- }
216
- ): AsyncIterable<T | Record<string, unknown>>
217
- ```
218
-
219
- **Example:**
220
-
221
- ```typescript
222
- const results = client.searchVectorStore("engine-id", "VectorStore1", "apple");
223
- for await (const result of results) {
224
- console.log(result);
225
- }
226
- ```
227
-
228
- ### Storage API
229
-
230
- #### getStorageDocumentByEventId
231
-
232
- Get a single storage document by EventId.
233
-
234
- ```typescript
235
- const document = await client.getStorageDocumentByEventId(
236
- engineId: string,
237
- eventId: string,
238
- options?: {
239
- filterFn?: (document: T | Record<string, unknown>) => boolean;
240
- schema?: z.ZodSchema<unknown>;
241
- }
242
- ): Promise<T | Record<string, unknown> | null>
243
- ```
244
-
245
- **Example:**
246
-
247
- ```typescript
248
- const document = await client.getStorageDocumentByEventId("engine-id", "event-id");
249
- if (document) {
250
- console.log(document);
251
- }
252
- ```
253
-
254
- #### getStorageDocumentByCustomerKey
255
-
256
- Get storage documents by CustomerKey with automatic pagination.
257
-
258
- ```typescript
259
- const documents = client.getStorageDocumentByCustomerKey(
260
- engineId: string,
261
- customerKey: string,
262
- options?: {
263
- pageNumber?: number; // Default: 1
264
- pageSize?: number; // Default: 25, max: 100
265
- filterFn?: (item: T | Record<string, unknown>) => boolean;
266
- schema?: z.ZodSchema<unknown>;
267
- }
268
- ): AsyncIterable<T | Record<string, unknown>>
269
- ```
270
-
271
- **Example:**
272
-
273
- ```typescript
274
- const documents = client.getStorageDocumentByCustomerKey("engine-id", "doc-123", {
275
- pageSize: 50
276
- });
277
-
278
- for await (const doc of documents) {
279
- console.log(doc);
280
- }
281
- ```
282
-
283
- #### queryStorageByJsonPath
284
-
285
- Query storage documents using JSONPath.
286
-
287
- ```typescript
288
- const documents = client.queryStorageByJsonPath(
289
- engineId: string,
290
- jsonPathQuery: string,
291
- options?: {
292
- filterFn?: (item: T | Record<string, unknown>) => boolean;
293
- schema?: z.ZodSchema<unknown>;
294
- }
295
- ): AsyncIterable<T | Record<string, unknown>>
296
- ```
297
-
298
- **Example:**
299
-
300
- ```typescript
301
- const documents = client.queryStorageByJsonPath("engine-id", "$.status:active");
302
- for await (const doc of documents) {
303
- console.log(doc);
304
- }
305
- ```
306
-
307
- #### listStorageDocuments
308
-
309
- List storage documents with automatic pagination.
310
-
311
- ```typescript
312
- const documents = client.listStorageDocuments(
313
- engineId: string,
314
- options?: {
315
- customerKey?: string;
316
- pageNumber?: number; // Default: 1
317
- pageSize?: number; // Default: 100, max: 100
318
- filterFn?: (item: T | Record<string, unknown>) => boolean;
319
- schema?: z.ZodSchema<unknown>;
320
- }
321
- ): AsyncIterable<T | Record<string, unknown>>
322
- ```
323
-
324
- **Example:**
325
-
326
- ```typescript
327
- // List all documents
328
- const documents = client.listStorageDocuments("engine-id");
329
-
330
- // List documents filtered by customerKey
331
- const filtered = client.listStorageDocuments("engine-id", {
332
- customerKey: "doc-123"
333
- });
334
-
335
- for await (const doc of documents) {
336
- console.log(doc);
337
- }
338
- ```
339
-
340
- ### Indexing API
341
-
342
- #### searchIndex
343
-
344
- Search index using Azure Search.
345
-
346
- ```typescript
347
- const results = client.searchIndex(
348
- projectId: string,
349
- engineId: string,
350
- query: Record<string, unknown>,
351
- options?: {
352
- filterFn?: (item: T | Record<string, unknown>) => boolean;
353
- schema?: z.ZodSchema<unknown>;
354
- }
355
- ): AsyncIterable<T | Record<string, unknown>>
356
- ```
357
-
358
- **Example:**
359
-
360
- ```typescript
361
- const results = client.searchIndex("project-id", "engine-id", {
362
- search: "example query"
363
- });
364
-
365
- for await (const result of results) {
366
- console.log(result);
367
- }
368
- ```
369
-
370
- ## Pagination
371
-
372
- Pagination is handled automatically by the SDK. Methods that return multiple results use async iterables that handle pagination internally:
373
-
374
- ```typescript
375
- // Automatically handles pagination - you don't need to manage pages manually
376
- const documents = client.listStorageDocuments("engine-id", {
377
- pageSize: 100
378
- });
379
-
380
- // Iterate through all pages automatically
381
- for await (const document of documents) {
382
- console.log(document);
383
- }
384
- ```
385
-
386
- Filtering is applied across all pages automatically:
387
-
388
- ```typescript
389
- // Filter is applied to all pages, not just the first page
390
- const documents = client.listStorageDocuments("engine-id", {
391
- filterFn: (doc) => {
392
- const customerKey = (doc as { CustomerKey?: string }).CustomerKey || "";
393
- return customerKey.startsWith("doc-");
394
- }
395
- });
396
-
397
- for await (const doc of documents) {
398
- // All documents from all pages that match the filter
399
- console.log(doc);
400
- }
401
- ```
402
-
403
- ## Complete Examples
404
-
405
- ### Example: Building a Simple Agent
406
-
407
- ```typescript
408
- import { RailEngine } from "@railtownai/railengine";
409
- import { z } from "zod";
410
-
411
- const DocumentSchema = z.object({
412
- id: z.string(),
413
- title: z.string(),
414
- content: z.string(),
415
- tags: z.array(z.string())
416
- });
417
-
418
- const client = new RailEngine({
419
- pat: process.env.ENGINE_PAT!,
420
- engineId: process.env.ENGINE_ID!,
421
- schema: DocumentSchema
422
- });
423
-
424
- async function searchDocuments(query: string) {
425
- // Search vector store
426
- const vectorResults = client.searchVectorStore(client.engineId, "VectorStore1", query, {
427
- filterFn: (doc) => {
428
- const tags = (doc as { tags?: string[] }).tags || [];
429
- return tags.includes("public");
430
- }
431
- });
432
-
433
- const results: unknown[] = [];
434
- for await (const result of vectorResults) {
435
- results.push(result);
436
- }
437
-
438
- return results;
439
- }
440
-
441
- // Usage
442
- const docs = await searchDocuments("machine learning");
443
- console.log(`Found ${docs.length} documents`);
444
- ```
445
-
446
- ### Example: Retrieving and Filtering Documents
447
-
448
- ```typescript
449
- import { RailEngine } from "@railtownai/railengine";
450
-
451
- const client = new RailEngine({
452
- pat: process.env.ENGINE_PAT!,
453
- engineId: process.env.ENGINE_ID!
454
- });
455
-
456
- // Get document by EventId
457
- const doc = await client.getStorageDocumentByEventId("engine-id", "event-123");
458
- if (doc) {
459
- console.log("Found document:", doc);
460
- }
461
-
462
- // Get documents by CustomerKey with filtering
463
- const customerDocs = client.getStorageDocumentByCustomerKey("engine-id", "customer-123", {
464
- filterFn: (doc) => {
465
- const version = (doc as { Version?: number }).Version || 0;
466
- const status = (doc as { Status?: string }).Status;
467
- return version > 1 && status === "active";
468
- }
469
- });
470
-
471
- for await (const doc of customerDocs) {
472
- console.log("Customer document:", doc);
473
- }
474
-
475
- // Query using JSONPath
476
- const activeDocs = client.queryStorageByJsonPath("engine-id", "$.status:active", {
477
- filterFn: (doc) => {
478
- const dateCreated = (doc as { DateCreated?: string }).DateCreated;
479
- return dateCreated ? new Date(dateCreated) > new Date("2024-01-01") : false;
480
- }
481
- });
482
-
483
- for await (const doc of activeDocs) {
484
- console.log("Active document:", doc);
485
- }
486
- ```
487
-
488
- ## API Reference
489
-
490
- ### RailEngine
491
-
492
- Main client class for retrieving data from Rail Engine.
493
-
494
- #### Constructor
495
-
496
- ```typescript
497
- new RailEngine(options?: RailEngineOptions<T>)
498
- ```
499
-
500
- **Options:**
501
-
502
- - `pat?: string` - Personal Access Token. If not provided, reads from `ENGINE_PAT` environment variable.
503
- - `engineId?: string` - Engine ID. If not provided, reads from `ENGINE_ID` environment variable.
504
- - `apiUrl?: string` - Base API URL. If not provided, reads from `RAILTOWN_API_URL` environment variable or defaults to production.
505
- - `schema?: z.ZodSchema<T>` - Optional Zod schema for validating retrieved data.
506
- - `timeout?: number` - Request timeout in milliseconds. Defaults to 30000 (30 seconds).
507
-
508
- **Example:**
509
-
510
- ```typescript
511
- const client = new RailEngine({
512
- pat: "your-pat-token",
513
- engineId: "your-engine-id",
514
- schema: MySchema,
515
- timeout: 60000
516
- });
517
- ```
518
-
519
- #### Properties
520
-
521
- - `pat: string` - Personal Access Token for authentication
522
- - `engineId: string` - Engine identifier
523
- - `apiUrl: string` - Base API URL (normalized)
524
-
525
- #### Methods
526
-
527
- All methods are documented above in the API Methods section.
528
-
529
- ## Error Handling
530
-
531
- The SDK uses graceful error handling for read operations:
532
-
533
- - **Read operations** return `null` or empty iterables on errors (graceful degradation)
534
- - **Configuration errors** (missing PAT, engineId) throw exceptions
535
-
536
- The SDK uses custom exception classes for different error scenarios:
537
-
538
- - `RailtownError` - Base error class
539
- - `RailtownUnauthorizedError` - Authentication failed (401)
540
- - `RailtownNotFoundError` - Resource not found (404)
541
- - `RailtownBadRequestError` - Bad request (400)
542
- - `RailtownConflictError` - Conflict (409)
543
- - `RailtownServerError` - Server error (500+)
544
-
545
- **Example:**
546
-
547
- ```typescript
548
- import { RailEngine, RailtownUnauthorizedError, RailtownBadRequestError } from "@railtownai/railengine";
549
-
550
- try {
551
- const client = new RailEngine({
552
- pat: "invalid-pat",
553
- engineId: "engine-id"
554
- });
555
- } catch (error) {
556
- if (error instanceof RailtownBadRequestError) {
557
- console.error("Invalid configuration:", error.message);
558
- }
559
- }
560
-
561
- // Read operations return null/empty on error
562
- const document = await client.getStorageDocumentByEventId("engine-id", "event-id");
563
- if (document === null) {
564
- console.log("Document not found or error occurred");
565
- }
566
- ```
567
-
568
- ## License
569
-
570
- See [LICENSE](../../LICENSE) file for details.
1
+ # @railtownai/railengine
2
+
3
+ JavaScript/TypeScript SDK for [Railtown AI Rail Engine](https://railengine.ai/) - Retrieval package. This package provides a simple interface for reading and searching data from Rail Engine.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @railtownai/railengine
9
+ ```
10
+
11
+ ## Requirements
12
+
13
+ - Node.js 20+
14
+ - TypeScript 5.0+ (optional, but recommended)
15
+
16
+ ## Quick Start
17
+
18
+ ### Basic Usage
19
+
20
+ ```typescript
21
+ import { RailEngine } from "@railtownai/railengine";
22
+
23
+ // ENGINE_PAT and ENGINE_ID are read from environment variables automatically
24
+
25
+ // Initialize client
26
+ const client = new RailEngine();
27
+
28
+ // Get storage document by EventId
29
+ const document = await client.getStorageDocumentByEventId({
30
+ eventId: "event-id"
31
+ });
32
+ console.log(document);
33
+ ```
34
+
35
+ ### Using Environment Variables
36
+
37
+ ```typescript
38
+ import { RailEngine } from "@railtownai/railengine";
39
+
40
+ const client = new RailEngine();
41
+
42
+ // Use client.engineId if you need it
43
+ const results = client.searchVectorStore(client.engineId, "VectorStore1", "query");
44
+ for await (const result of results) {
45
+ console.log(result);
46
+ }
47
+ ```
48
+
49
+ ## Zod Schema Support
50
+
51
+ You can provide a Zod schema during client initialization to automatically validate retrieved data:
52
+
53
+ ```typescript
54
+ import { z } from "zod";
55
+ import { RailEngine } from "@railtownai/railengine";
56
+
57
+ const FoodDiaryItemSchema = z.object({
58
+ food_name: z.string(),
59
+ calories: z.number(),
60
+ carbs: z.number(),
61
+ proteins: z.number(),
62
+ fats: z.number()
63
+ });
64
+
65
+ type FoodDiaryItem = z.infer<typeof FoodDiaryItemSchema>;
66
+
67
+ // Initialize with schema
68
+ const client = new RailEngine({
69
+ schema: FoodDiaryItemSchema
70
+ });
71
+
72
+ // Results automatically validated against FoodDiaryItemSchema
73
+ const results = client.searchVectorStore({
74
+ vectorStore: "VectorStore1",
75
+ query: "apple"
76
+ });
77
+ for await (const item of results) {
78
+ // item is FoodDiaryItem
79
+ console.log(item.food_name, item.calories);
80
+ }
81
+ ```
82
+
83
+ ## API Methods
84
+
85
+ ### Embeddings API
86
+
87
+ #### searchVectorStore
88
+
89
+ Search a vector store using semantic similarity.
90
+
91
+ **Example:**
92
+
93
+ ```typescript
94
+ const results = client.searchVectorStore({
95
+ engineId: "engine-id", // Optional, defaults to process.env.ENGINE_ID
96
+ vectorStore: "VectorStore1",
97
+ query: "apple"
98
+ });
99
+ for await (const result of results) {
100
+ console.log(result);
101
+ }
102
+ ```
103
+
104
+ ### Storage API
105
+
106
+ #### getStorageDocumentByEventId
107
+
108
+ Get a single storage document by EventId.
109
+
110
+ **Example:**
111
+
112
+ ```typescript
113
+ const document = await client.getStorageDocumentByEventId({
114
+ eventId: "event-id",
115
+ engineId: "engine-id" // Optional, defaults to process.env.ENGINE_ID
116
+ });
117
+ if (document) {
118
+ console.log(document);
119
+ }
120
+ ```
121
+
122
+ #### getStorageDocumentByCustomerKey
123
+
124
+ Get storage documents by CustomerKey with automatic pagination.
125
+
126
+ **Example:**
127
+
128
+ ```typescript
129
+ const documents = client.getStorageDocumentByCustomerKey({
130
+ customerKey: "doc-123",
131
+ engineId: "engine-id", // Optional, defaults to process.env.ENGINE_ID
132
+ pageSize: 50
133
+ });
134
+
135
+ for await (const doc of documents) {
136
+ console.log(doc);
137
+ }
138
+ ```
139
+
140
+ #### queryStorageByJsonPath
141
+
142
+ Query storage documents using JSONPath.
143
+
144
+ ```typescript
145
+ const documents = client.queryStorageByJsonPath(
146
+ engineId: string,
147
+ jsonPathQuery: string,
148
+ options?: {
149
+ filterFn?: (item: T | Record<string, unknown>) => boolean;
150
+ schema?: z.ZodSchema<unknown>;
151
+ }
152
+ ): AsyncIterable<T | Record<string, unknown>>
153
+ ```
154
+
155
+ **Example:**
156
+
157
+ ```typescript
158
+ const documents = await client.queryStorageByJsonPath({
159
+ engineId: "engine-id",
160
+ jsonPathQuery: "$.status:active"
161
+ });
162
+ for await (const doc of documents) {
163
+ console.log(doc);
164
+ }
165
+ ```
166
+
167
+ #### listStorageDocuments
168
+
169
+ List storage documents with automatic pagination.
170
+
171
+ **Example:**
172
+
173
+ ```typescript
174
+ // List all documents
175
+ const documents = await client.listStorageDocuments({
176
+ engineId: "engine-id"
177
+ });
178
+
179
+ // List documents filtered by customerKey
180
+ const filtered = await client.listStorageDocuments({
181
+ engineId: "engine-id",
182
+ customerKey: "doc-123"
183
+ });
184
+
185
+ for await (const doc of documents) {
186
+ console.log(doc);
187
+ }
188
+ ```
189
+
190
+ ### Indexing API
191
+
192
+ #### searchIndex
193
+
194
+ Search Railengine Index.
195
+
196
+ **Example:**
197
+
198
+ ```typescript
199
+ const results = client.searchIndex("engine-id", { search: "example query" });
200
+
201
+ for await (const result of results) {
202
+ console.log(result);
203
+ }
204
+ ```
205
+
206
+ ## License
207
+
208
+ MIT.