@march-ai/history-sdk 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 March Team
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,449 @@
1
+ # March History SDK (TypeScript)
2
+
3
+ > A universal TypeScript SDK for the March AI Conversation History API - Works in both Node.js and browsers
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
7
+ [![Node.js >= 18](https://img.shields.io/badge/Node.js-%3E=18-green.svg)](https://nodejs.org/)
8
+
9
+ ## âœĻ Features
10
+
11
+ - 🌍 **Universal**: Works in Node.js (18+) and all modern browsers
12
+ - 🔐 **Dual Authentication**: Supports both API keys (backend) and JWT bearer tokens (frontend)
13
+ - 📘 **Full TypeScript Support**: Complete type safety with auto-generated types
14
+ - ✅ **Runtime Validation**: Uses Zod for request/response validation
15
+ - 🔄 **Auto-Retry**: Exponential backoff with jitter for transient failures
16
+ - 📄 **Auto-Pagination**: Async generators for seamless iteration
17
+ - ðŸŽŊ **Resource-Based API**: Clean, intuitive method organization
18
+ - ðŸŠķ **Lightweight**: ~45KB total, ~12KB gzipped
19
+ - ðŸŒē **Tree-Shakeable**: Optimized for frontend bundles
20
+
21
+ ## ðŸ“Ķ Installation
22
+
23
+ ```bash
24
+ npm install @march/history-sdk
25
+ # or
26
+ yarn add @march/history-sdk
27
+ # or
28
+ pnpm add @march/history-sdk
29
+ ```
30
+
31
+ ## 🚀 Quick Start
32
+
33
+ ### Node.js (Backend)
34
+
35
+ ```typescript
36
+ import { MarchHistoryClient, MessageRole } from '@march/history-sdk';
37
+
38
+ // Initialize with API key
39
+ const client = new MarchHistoryClient({
40
+ baseUrl: 'http://localhost:8000',
41
+ apiKey: 'your-api-key', // Sent as X-API-Key header
42
+ });
43
+
44
+ // Create a conversation
45
+ const conversation = await client.conversations.create({
46
+ tenant_name: 'acme-corp',
47
+ user_id: 'user-123',
48
+ title: 'Customer Support Session',
49
+ metadata: { session_id: 'sess-456' },
50
+ });
51
+
52
+ // Add messages
53
+ await client.messages.create({
54
+ conversation_id: conversation.id,
55
+ role: MessageRole.USER,
56
+ content: 'Hello, I need help!',
57
+ });
58
+
59
+ await client.messages.create({
60
+ conversation_id: conversation.id,
61
+ role: MessageRole.ASSISTANT,
62
+ content: 'How can I help you today?',
63
+ });
64
+
65
+ // List messages
66
+ const messages = await client.messages.list({
67
+ conversation_id: conversation.id,
68
+ });
69
+
70
+ console.log(`Found ${messages.length} messages`);
71
+ ```
72
+
73
+ ### Browser (Frontend)
74
+
75
+ ```typescript
76
+ import { MarchHistoryClient, ConversationStatus } from '@march/history-sdk';
77
+
78
+ // Get JWT from your auth provider
79
+ const jwtToken = await getJWTToken();
80
+
81
+ // Initialize with bearer token
82
+ const client = new MarchHistoryClient({
83
+ baseUrl: 'https://api.example.com',
84
+ bearerToken: jwtToken, // Sent as Authorization: Bearer header
85
+ });
86
+
87
+ // List conversations
88
+ const conversations = await client.conversations.list({
89
+ tenant_name: 'my-tenant',
90
+ status: ConversationStatus.ACTIVE,
91
+ });
92
+
93
+ console.log(`Found ${conversations.length} conversations`);
94
+ ```
95
+
96
+ ### Dual Authentication
97
+
98
+ ```typescript
99
+ // Some APIs require both API key and JWT
100
+ const client = new MarchHistoryClient({
101
+ baseUrl: 'https://api.example.com',
102
+ apiKey: 'project-api-key', // X-API-Key header
103
+ bearerToken: userJwtToken, // Authorization: Bearer header
104
+ });
105
+
106
+ // Both headers will be sent with every request
107
+ ```
108
+
109
+ ## 📚 API Reference
110
+
111
+ ### Client Initialization
112
+
113
+ ```typescript
114
+ const client = new MarchHistoryClient({
115
+ baseUrl?: string; // Default: 'http://localhost:8000'
116
+ timeout?: number; // Default: 30000 (ms)
117
+ maxRetries?: number; // Default: 3
118
+ apiKey?: string; // Optional API key
119
+ bearerToken?: string; // Optional JWT token
120
+ customHeaders?: Record<string, string>;
121
+ });
122
+ ```
123
+
124
+ ### Tenants
125
+
126
+ ```typescript
127
+ // List tenants
128
+ const tenants = await client.tenants.list({ offset: 0, limit: 100 });
129
+
130
+ // Get tenant by ID
131
+ const tenant = await client.tenants.getById(1);
132
+
133
+ // Get tenant by name
134
+ const tenant = await client.tenants.getByName('acme-corp');
135
+
136
+ // Auto-pagination
137
+ for await (const tenant of client.tenants.listIter()) {
138
+ console.log(tenant.name);
139
+ }
140
+ ```
141
+
142
+ ### Conversations
143
+
144
+ ```typescript
145
+ // Create conversation
146
+ const conv = await client.conversations.create({
147
+ tenant_name: 'acme-corp',
148
+ user_id: 'user-123',
149
+ title: 'Support Chat',
150
+ agent_identifier: 'support-bot-v1',
151
+ status: ConversationStatus.ACTIVE,
152
+ metadata: { session_id: 'sess-456' },
153
+ });
154
+
155
+ // Get conversation
156
+ const conv = await client.conversations.getById(1);
157
+
158
+ // Get conversation with messages
159
+ const conv = await client.conversations.getById(1, true);
160
+
161
+ // List conversations
162
+ const convs = await client.conversations.list({
163
+ tenant_name: 'acme-corp',
164
+ status: ConversationStatus.ACTIVE,
165
+ offset: 0,
166
+ limit: 100,
167
+ });
168
+
169
+ // Update conversation
170
+ const updated = await client.conversations.update(1, {
171
+ title: 'New Title',
172
+ metadata: { updated: true },
173
+ });
174
+
175
+ // Archive/unarchive
176
+ await client.conversations.archive(1);
177
+ await client.conversations.unarchive(1);
178
+
179
+ // Delete conversation
180
+ await client.conversations.deleteById(1);
181
+
182
+ // Search conversations
183
+ const results = await client.conversations.search({
184
+ q: 'support',
185
+ status: ConversationStatus.ACTIVE,
186
+ });
187
+
188
+ // Auto-pagination
189
+ for await (const conv of client.conversations.listIter({ tenant_name: 'acme' })) {
190
+ console.log(conv.title);
191
+ }
192
+ ```
193
+
194
+ ### Messages
195
+
196
+ ```typescript
197
+ // Create single message
198
+ const msg = await client.messages.create({
199
+ conversation_id: 1,
200
+ role: MessageRole.USER,
201
+ content: 'Hello!',
202
+ metadata: { client_ip: '192.168.1.1' },
203
+ });
204
+
205
+ // Batch create messages
206
+ const messages = await client.messages.createBatch(1, [
207
+ { role: MessageRole.USER, content: 'Hello!' },
208
+ { role: MessageRole.ASSISTANT, content: 'Hi! How can I help?' },
209
+ ]);
210
+
211
+ // List messages
212
+ const messages = await client.messages.list({
213
+ conversation_id: 1,
214
+ role: MessageRole.USER,
215
+ offset: 0,
216
+ limit: 100,
217
+ });
218
+
219
+ // Get message by ID
220
+ const msg = await client.messages.getById(1);
221
+
222
+ // Search messages in conversation
223
+ const results = await client.messages.search({
224
+ conversation_id: 1,
225
+ q: 'help',
226
+ role: MessageRole.USER,
227
+ });
228
+
229
+ // Search messages globally
230
+ const results = await client.messages.searchGlobal({
231
+ q: 'error',
232
+ conversation_id: 1,
233
+ });
234
+
235
+ // Auto-pagination
236
+ for await (const msg of client.messages.listIter({ conversation_id: 1 })) {
237
+ console.log(msg.content);
238
+ }
239
+ ```
240
+
241
+ ## 🔄 Auto-Pagination
242
+
243
+ The SDK provides two methods for listing resources:
244
+
245
+ 1. **`.list()`** - Returns a single page of results
246
+ 2. **`.listIter()`** - Returns an async generator that automatically fetches all pages
247
+
248
+ ```typescript
249
+ // Manual pagination
250
+ const page1 = await client.conversations.list({ offset: 0, limit: 100 });
251
+ const page2 = await client.conversations.list({ offset: 100, limit: 100 });
252
+
253
+ // Auto-pagination (recommended)
254
+ for await (const conversation of client.conversations.listIter()) {
255
+ console.log(conversation.title);
256
+ // Automatically fetches next page when needed
257
+ }
258
+
259
+ // Iterate by pages
260
+ for await (const page of client.conversations.listIter().pages()) {
261
+ console.log(`Page has ${page.length} items`);
262
+ }
263
+
264
+ // Limit total items fetched
265
+ const paginator = client.conversations.listIter({}, 100, 500); // pageSize=100, maxItems=500
266
+ for await (const conv of paginator) {
267
+ // Will stop after 500 items
268
+ }
269
+ ```
270
+
271
+ ## ðŸšĻ Error Handling
272
+
273
+ The SDK provides specific error classes for different HTTP status codes:
274
+
275
+ ```typescript
276
+ import {
277
+ NotFoundError,
278
+ ValidationError,
279
+ ConflictError,
280
+ ServerError,
281
+ NetworkError,
282
+ RetryError,
283
+ } from '@march/history-sdk';
284
+
285
+ try {
286
+ const conv = await client.conversations.getById(999);
287
+ } catch (error) {
288
+ if (error instanceof NotFoundError) {
289
+ console.error('Conversation not found:', error.statusCode);
290
+ } else if (error instanceof ValidationError) {
291
+ console.error('Invalid request:', error.details);
292
+ } else if (error instanceof ConflictError) {
293
+ console.error('Duplicate sequence number:', error.message);
294
+ } else if (error instanceof ServerError) {
295
+ console.error('Server error:', error.statusCode);
296
+ } else if (error instanceof NetworkError) {
297
+ console.error('Network error:', error.message);
298
+ } else if (error instanceof RetryError) {
299
+ console.error('Max retries exceeded:', error.lastException);
300
+ } else {
301
+ console.error('Unexpected error:', error);
302
+ }
303
+ }
304
+ ```
305
+
306
+ ### Client-Side Validation
307
+
308
+ The SDK validates request data using Zod before sending to the API:
309
+
310
+ ```typescript
311
+ try {
312
+ await client.messages.create({
313
+ conversation_id: 1,
314
+ role: 'invalid_role', // Invalid role
315
+ content: 'test',
316
+ });
317
+ } catch (error) {
318
+ // ZodError: Validation failed
319
+ console.error('Client-side validation failed:', error);
320
+ }
321
+ ```
322
+
323
+ ## 🔧 Advanced Configuration
324
+
325
+ ### Custom Retry Configuration
326
+
327
+ ```typescript
328
+ const client = new MarchHistoryClient({
329
+ baseUrl: 'http://localhost:8000',
330
+ retryConfig: {
331
+ maxRetries: 5,
332
+ backoffFactor: 2.0,
333
+ retryStatusCodes: [408, 429, 500, 502, 503, 504],
334
+ maxBackoffSeconds: 120,
335
+ },
336
+ });
337
+ ```
338
+
339
+ ### Custom Headers
340
+
341
+ ```typescript
342
+ const client = new MarchHistoryClient({
343
+ baseUrl: 'http://localhost:8000',
344
+ customHeaders: {
345
+ 'X-Custom-Header': 'value',
346
+ 'X-Request-ID': crypto.randomUUID(),
347
+ },
348
+ });
349
+ ```
350
+
351
+ ### Manual Cleanup
352
+
353
+ ```typescript
354
+ const client = new MarchHistoryClient({ baseUrl: 'http://localhost:8000' });
355
+
356
+ // Use the client...
357
+ await client.conversations.list();
358
+
359
+ // Optional: Explicitly close connections
360
+ client.close();
361
+ ```
362
+
363
+ ## 📝 TypeScript Types
364
+
365
+ The SDK exports all TypeScript types for use in your code:
366
+
367
+ ```typescript
368
+ import type {
369
+ Tenant,
370
+ Conversation,
371
+ Message,
372
+ ConversationStatus,
373
+ MessageRole,
374
+ CreateConversationParams,
375
+ ListConversationsParams,
376
+ SearchConversationsParams,
377
+ CreateMessageParams,
378
+ ListMessagesParams,
379
+ } from '@march/history-sdk';
380
+
381
+ const params: CreateConversationParams = {
382
+ tenant_name: 'acme-corp',
383
+ user_id: 'user-123',
384
+ title: 'Support Chat',
385
+ metadata: { session_id: 'sess-456' },
386
+ };
387
+
388
+ const conversation: Conversation = await client.conversations.create(params);
389
+ ```
390
+
391
+ ## 🌐 Browser Usage
392
+
393
+ The SDK works seamlessly in browsers. Here's an example with Vite:
394
+
395
+ ```typescript
396
+ // src/main.ts
397
+ import { MarchHistoryClient, MessageRole } from '@march/history-sdk';
398
+
399
+ async function main() {
400
+ const client = new MarchHistoryClient({
401
+ baseUrl: 'https://api.example.com',
402
+ bearerToken: localStorage.getItem('jwt_token'),
403
+ });
404
+
405
+ const conversations = await client.conversations.list({
406
+ tenant_name: 'my-tenant',
407
+ });
408
+
409
+ console.log('Conversations:', conversations);
410
+ }
411
+
412
+ main().catch(console.error);
413
+ ```
414
+
415
+ ## 📊 Bundle Size
416
+
417
+ - **Unminified**: ~138 KB (ESM), ~139 KB (CJS)
418
+ - **With Zod**: ~45-50 KB total
419
+ - **Gzipped**: ~12-15 KB
420
+ - **Tree-shakeable**: Only import what you use
421
+
422
+ ## 🏗ïļ Architecture
423
+
424
+ The SDK follows these design patterns:
425
+
426
+ - **Resource-based organization**: Each API domain (tenants, conversations, messages) is a separate resource class
427
+ - **Universal compatibility**: Uses native `fetch` API (Node.js 18+ and all browsers)
428
+ - **Type safety**: Zod schemas provide runtime validation and auto-generate TypeScript types
429
+ - **Async-first design**: All operations use `async/await`
430
+ - **Retry logic**: Exponential backoff with jitter for transient failures
431
+ - **Error handling**: Status code → specific error class mapping
432
+
433
+ ## ðŸĪ Contributing
434
+
435
+ Contributions are welcome! Please feel free to submit a Pull Request.
436
+
437
+ ## 📄 License
438
+
439
+ MIT ÂĐ March Team
440
+
441
+ ## 🔗 Links
442
+
443
+ - [API Documentation](API_DOCUMENTATION.md)
444
+ - [GitHub Repository](#)
445
+ - [NPM Package](#)
446
+
447
+ ---
448
+
449
+ Built with âĪïļ using TypeScript, Zod, and tsup.