@attrove/sdk 0.1.2 → 0.1.4

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.
Files changed (107) hide show
  1. package/cjs/README.md +247 -0
  2. package/cjs/package.json +56 -0
  3. package/cjs/src/__mocks__/version.js +17 -0
  4. package/cjs/src/__mocks__/version.js.map +1 -0
  5. package/cjs/src/admin-client.js +221 -0
  6. package/cjs/src/admin-client.js.map +1 -0
  7. package/cjs/src/client.js +312 -0
  8. package/cjs/src/client.js.map +1 -0
  9. package/cjs/src/constants.js +69 -0
  10. package/cjs/src/constants.js.map +1 -0
  11. package/cjs/src/errors/index.js +307 -0
  12. package/cjs/src/errors/index.js.map +1 -0
  13. package/cjs/src/index.js +98 -0
  14. package/cjs/src/index.js.map +1 -0
  15. package/cjs/src/resources/conversations.js +95 -0
  16. package/cjs/src/resources/conversations.js.map +1 -0
  17. package/cjs/src/resources/index.js +17 -0
  18. package/cjs/src/resources/index.js.map +1 -0
  19. package/cjs/src/resources/integrations.js +69 -0
  20. package/cjs/src/resources/integrations.js.map +1 -0
  21. package/cjs/src/resources/messages.js +98 -0
  22. package/cjs/src/resources/messages.js.map +1 -0
  23. package/cjs/src/resources/query.js +143 -0
  24. package/cjs/src/resources/query.js.map +1 -0
  25. package/cjs/src/resources/users.js +91 -0
  26. package/cjs/src/resources/users.js.map +1 -0
  27. package/cjs/src/types/index.js +292 -0
  28. package/cjs/src/types/index.js.map +1 -0
  29. package/cjs/src/utils/fetch.js +417 -0
  30. package/cjs/src/utils/fetch.js.map +1 -0
  31. package/cjs/src/utils/index.js +12 -0
  32. package/cjs/src/utils/index.js.map +1 -0
  33. package/cjs/src/utils/streaming.js +368 -0
  34. package/cjs/src/utils/streaming.js.map +1 -0
  35. package/cjs/src/version.js +31 -0
  36. package/cjs/src/version.js.map +1 -0
  37. package/esm/README.md +247 -0
  38. package/esm/package.json +56 -0
  39. package/esm/src/__mocks__/version.js +12 -0
  40. package/esm/src/__mocks__/version.js.map +1 -0
  41. package/esm/src/admin-client.js +216 -0
  42. package/esm/src/admin-client.js.map +1 -0
  43. package/esm/src/client.js +308 -0
  44. package/esm/src/client.js.map +1 -0
  45. package/esm/src/constants.js +65 -0
  46. package/esm/src/constants.js.map +1 -0
  47. package/esm/src/errors/index.js +285 -0
  48. package/esm/src/errors/index.js.map +1 -0
  49. package/esm/src/index.js +68 -0
  50. package/esm/src/index.js.map +1 -0
  51. package/esm/src/resources/conversations.js +91 -0
  52. package/esm/src/resources/conversations.js.map +1 -0
  53. package/esm/src/resources/index.js +9 -0
  54. package/esm/src/resources/index.js.map +1 -0
  55. package/esm/src/resources/integrations.js +65 -0
  56. package/esm/src/resources/integrations.js.map +1 -0
  57. package/esm/src/resources/messages.js +94 -0
  58. package/esm/src/resources/messages.js.map +1 -0
  59. package/esm/src/resources/query.js +139 -0
  60. package/esm/src/resources/query.js.map +1 -0
  61. package/esm/src/resources/users.js +87 -0
  62. package/esm/src/resources/users.js.map +1 -0
  63. package/esm/src/types/index.js +277 -0
  64. package/esm/src/types/index.js.map +1 -0
  65. package/esm/src/utils/fetch.js +413 -0
  66. package/esm/src/utils/fetch.js.map +1 -0
  67. package/esm/src/utils/index.js +6 -0
  68. package/esm/src/utils/index.js.map +1 -0
  69. package/esm/src/utils/streaming.js +363 -0
  70. package/esm/src/utils/streaming.js.map +1 -0
  71. package/esm/src/version.js +26 -0
  72. package/esm/src/version.js.map +1 -0
  73. package/package.json +16 -9
  74. package/types/src/__mocks__/version.d.ts +8 -0
  75. package/types/src/__mocks__/version.d.ts.map +1 -0
  76. package/types/src/admin-client.d.ts +144 -0
  77. package/types/src/admin-client.d.ts.map +1 -0
  78. package/types/src/client.d.ts +233 -0
  79. package/types/src/client.d.ts.map +1 -0
  80. package/types/src/constants.d.ts +47 -0
  81. package/types/src/constants.d.ts.map +1 -0
  82. package/types/src/errors/index.d.ts +206 -0
  83. package/types/src/errors/index.d.ts.map +1 -0
  84. package/types/src/index.d.ts +65 -0
  85. package/types/src/index.d.ts.map +1 -0
  86. package/types/src/resources/conversations.d.ts +81 -0
  87. package/types/src/resources/conversations.d.ts.map +1 -0
  88. package/types/src/resources/index.d.ts +12 -0
  89. package/types/src/resources/index.d.ts.map +1 -0
  90. package/types/src/resources/integrations.d.ts +63 -0
  91. package/types/src/resources/integrations.d.ts.map +1 -0
  92. package/types/src/resources/messages.d.ts +69 -0
  93. package/types/src/resources/messages.d.ts.map +1 -0
  94. package/types/src/resources/query.d.ts +86 -0
  95. package/types/src/resources/query.d.ts.map +1 -0
  96. package/types/src/resources/users.d.ts +88 -0
  97. package/types/src/resources/users.d.ts.map +1 -0
  98. package/types/src/types/index.d.ts +807 -0
  99. package/types/src/types/index.d.ts.map +1 -0
  100. package/types/src/utils/fetch.d.ts +161 -0
  101. package/types/src/utils/fetch.d.ts.map +1 -0
  102. package/types/src/utils/index.d.ts +8 -0
  103. package/types/src/utils/index.d.ts.map +1 -0
  104. package/types/src/utils/streaming.d.ts +210 -0
  105. package/types/src/utils/streaming.d.ts.map +1 -0
  106. package/types/src/version.d.ts +21 -0
  107. package/types/src/version.d.ts.map +1 -0
@@ -0,0 +1,368 @@
1
+ "use strict";
2
+ /**
3
+ * WebSocket Streaming Utilities
4
+ *
5
+ * Provides WebSocket connection management for streaming LLM responses.
6
+ *
7
+ * Security Note: The WebSocket connection passes the authentication token
8
+ * as a query parameter. While this is a common pattern for WebSocket auth
9
+ * (since WebSocket doesn't support custom headers in browsers), be aware that:
10
+ * - Tokens may appear in server access logs
11
+ * - Tokens may be visible in network inspection tools
12
+ * - Using short-lived tokens is recommended for production use
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.generateMessageId = exports.StreamingClient = void 0;
16
+ const types_1 = require("../types");
17
+ const errors_1 = require("../errors");
18
+ const types_2 = require("../types");
19
+ const constants_1 = require("../constants");
20
+ /**
21
+ * Streaming query client for WebSocket-based LLM responses.
22
+ *
23
+ * Provides real-time streaming of AI-generated answers with support for:
24
+ * - Progress callbacks for each chunk
25
+ * - State change notifications
26
+ * - Cancellation via AbortSignal
27
+ * - Automatic cleanup on completion or error
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const streaming = new StreamingClient(baseUrl, apiKey);
32
+ * try {
33
+ * const result = await streaming.stream(query, messageId, history, options, {
34
+ * onChunk: (chunk) => console.log(chunk),
35
+ * });
36
+ * console.log('Answer:', result.answer);
37
+ * } finally {
38
+ * streaming.close();
39
+ * }
40
+ * ```
41
+ */
42
+ class StreamingClient {
43
+ constructor(baseUrl, token) {
44
+ this.ws = null;
45
+ this.currentMessageId = null;
46
+ // Convert HTTP URL to WebSocket URL
47
+ const wsBaseUrl = baseUrl.replace(/^http/, 'ws');
48
+ this.wsUrl = `${wsBaseUrl}/ws/llm-stream`;
49
+ this.token = token;
50
+ }
51
+ /**
52
+ * Connect to the WebSocket server.
53
+ *
54
+ * @throws {TimeoutError} If connection times out
55
+ * @throws {NetworkError} If connection fails
56
+ */
57
+ async connect(timeout = constants_1.DEFAULT_TIMEOUT) {
58
+ return new Promise((resolve, reject) => {
59
+ const timeoutId = setTimeout(() => {
60
+ reject(new errors_1.TimeoutError(`WebSocket connection timed out after ${timeout}ms`));
61
+ }, timeout);
62
+ try {
63
+ // Note: Token is passed as query parameter because WebSocket API
64
+ // doesn't support custom headers in browsers. This is a common pattern
65
+ // but means the token may appear in server logs.
66
+ const url = new URL(this.wsUrl);
67
+ url.searchParams.set('token', this.token);
68
+ const ws = new WebSocket(url.toString());
69
+ ws.onopen = () => {
70
+ clearTimeout(timeoutId);
71
+ resolve(ws);
72
+ };
73
+ ws.onerror = () => {
74
+ clearTimeout(timeoutId);
75
+ reject(new errors_1.NetworkError(`WebSocket connection to ${this.wsUrl} failed. Check your network connection and ensure the API endpoint is accessible.`));
76
+ };
77
+ ws.onclose = (event) => {
78
+ if (event.code !== 1000) {
79
+ clearTimeout(timeoutId);
80
+ const reason = (0, constants_1.getWsCloseReason)(event.code);
81
+ reject(new errors_1.NetworkError(`WebSocket closed during connection (code ${event.code}: ${reason}). This may indicate a server issue or network problem.`));
82
+ }
83
+ };
84
+ }
85
+ catch (err) {
86
+ clearTimeout(timeoutId);
87
+ reject(new errors_1.NetworkError(`Failed to create WebSocket: ${err instanceof Error ? err.message : String(err)}`));
88
+ }
89
+ });
90
+ }
91
+ /**
92
+ * Stream a query response.
93
+ *
94
+ * @param query - The natural language question to answer
95
+ * @param messageId - Unique message ID for tracking this stream
96
+ * @param history - Conversation history for context
97
+ * @param queryOptions - Query options (filters, timezone, etc.)
98
+ * @param streamOptions - Streaming options (callbacks, timeout, etc.)
99
+ * @returns Stream result with full answer and metadata
100
+ *
101
+ * @throws {NetworkError} If WebSocket connection fails or errors during streaming
102
+ * @throws {TimeoutError} If connection times out
103
+ * @throws {AttroveError} If the server returns an error
104
+ */
105
+ async stream(query, messageId, history, queryOptions = {}, streamOptions = {}) {
106
+ const { onChunk, onState, onStart, onError, onEnd, onWarning, signal, timeout = constants_1.DEFAULT_TIMEOUT } = streamOptions;
107
+ // Store warning callback for use in cancel() and cleanup()
108
+ this.onWarning = onWarning;
109
+ let answer = '';
110
+ let usedMessageIds = [];
111
+ let cancelled = false;
112
+ let completed = false;
113
+ // Connect to WebSocket
114
+ this.ws = await this.connect(timeout);
115
+ this.currentMessageId = messageId;
116
+ return new Promise((resolve, reject) => {
117
+ if (!this.ws) {
118
+ reject(new errors_1.NetworkError('WebSocket not connected'));
119
+ return;
120
+ }
121
+ const ws = this.ws;
122
+ // Track abort handler for cleanup
123
+ let abortHandler;
124
+ // Cleanup function to remove listeners and close connection
125
+ const cleanupAndFinish = () => {
126
+ completed = true;
127
+ if (signal && abortHandler) {
128
+ signal.removeEventListener('abort', abortHandler);
129
+ }
130
+ this.cleanup();
131
+ };
132
+ // Handle abort signal
133
+ if (signal) {
134
+ abortHandler = () => {
135
+ if (!completed) {
136
+ this.cancel();
137
+ cancelled = true;
138
+ }
139
+ };
140
+ signal.addEventListener('abort', abortHandler);
141
+ // Check if already aborted
142
+ if (signal.aborted) {
143
+ this.cancel();
144
+ cancelled = true;
145
+ }
146
+ }
147
+ // Send the query to the server after connection is established
148
+ const queryPayload = {
149
+ type: 'query',
150
+ message_id: messageId,
151
+ query,
152
+ client_timezone: queryOptions.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone,
153
+ history: history.length > 0 ? history : undefined,
154
+ integration_ids: queryOptions.integrationIds,
155
+ conversation_ids: queryOptions.conversationIds,
156
+ allow_bot_messages: queryOptions.allowBotMessages,
157
+ expand: queryOptions.includeSources ? 'sources' : undefined,
158
+ };
159
+ try {
160
+ ws.send(JSON.stringify(queryPayload));
161
+ }
162
+ catch (err) {
163
+ const error = new errors_1.NetworkError(`Failed to send query to server: ${err instanceof Error ? err.message : String(err)}`);
164
+ onError?.(error);
165
+ cleanupAndFinish();
166
+ reject(error);
167
+ return;
168
+ }
169
+ ws.onmessage = (event) => {
170
+ // Parse JSON separately to provide better error messages
171
+ let parsed;
172
+ try {
173
+ parsed = JSON.parse(event.data);
174
+ }
175
+ catch (parseErr) {
176
+ const error = new errors_1.AttroveError(`Failed to parse stream message: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`, types_2.ErrorCodes.INTERNAL_ERROR, undefined, { category: 'parse', rawDataPreview: String(event.data).substring(0, 200) });
177
+ onError?.(error);
178
+ cleanupAndFinish();
179
+ reject(error);
180
+ return;
181
+ }
182
+ // Validate the frame structure at runtime
183
+ if (!(0, types_1.isValidStreamFrame)(parsed)) {
184
+ const error = new errors_1.AttroveError('Received invalid stream frame format from server', types_2.ErrorCodes.INTERNAL_ERROR, undefined, { category: 'parse', rawDataPreview: JSON.stringify(parsed).substring(0, 200) });
185
+ onError?.(error);
186
+ cleanupAndFinish();
187
+ reject(error);
188
+ return;
189
+ }
190
+ const frame = parsed;
191
+ // Verify message ID matches - log mismatch for debugging
192
+ if (frame.message_id !== messageId) {
193
+ const warningContext = {
194
+ expected: messageId,
195
+ received: frame.message_id,
196
+ frameType: frame.type,
197
+ };
198
+ if (onWarning) {
199
+ onWarning('Received message with mismatched message_id, ignoring', warningContext);
200
+ }
201
+ else {
202
+ // prettier-ignore
203
+ console.warn('[AttroveSDK] Received message with mismatched message_id, ignoring:', warningContext);
204
+ }
205
+ return;
206
+ }
207
+ // Process the parsed frame - callback errors will propagate naturally
208
+ switch (frame.type) {
209
+ case 'stream_start':
210
+ onStart?.();
211
+ break;
212
+ case 'state':
213
+ onState?.(frame.state);
214
+ break;
215
+ case 'chunk':
216
+ answer += frame.content;
217
+ onChunk?.(frame.content);
218
+ break;
219
+ case 'message_ids':
220
+ usedMessageIds = frame.used_message_ids;
221
+ break;
222
+ case 'error': {
223
+ const error = new errors_1.AttroveError(frame.error, types_2.ErrorCodes.INTERNAL_ERROR);
224
+ onError?.(error);
225
+ cleanupAndFinish();
226
+ reject(error);
227
+ break;
228
+ }
229
+ case 'end': {
230
+ cancelled = frame.reason === 'cancelled';
231
+ if (frame.used_message_ids) {
232
+ usedMessageIds = frame.used_message_ids;
233
+ }
234
+ onEnd?.(frame.reason);
235
+ // Build updated history
236
+ const updatedHistory = [
237
+ ...history,
238
+ { role: 'assistant', content: answer },
239
+ ];
240
+ cleanupAndFinish();
241
+ resolve({
242
+ answer,
243
+ history: updatedHistory,
244
+ usedMessageIds,
245
+ cancelled,
246
+ });
247
+ break;
248
+ }
249
+ }
250
+ };
251
+ ws.onerror = () => {
252
+ if (!completed) {
253
+ const error = new errors_1.NetworkError(`WebSocket error during streaming. The connection was interrupted. You may need to retry the query.`);
254
+ onError?.(error);
255
+ cleanupAndFinish();
256
+ reject(error);
257
+ }
258
+ };
259
+ ws.onclose = (event) => {
260
+ if (!completed && event.code !== 1000) {
261
+ const reason = (0, constants_1.getWsCloseReason)(event.code);
262
+ const error = new errors_1.NetworkError(`WebSocket closed unexpectedly (code ${event.code}: ${reason}). The stream may need to be retried.`);
263
+ onError?.(error);
264
+ cleanupAndFinish();
265
+ reject(error);
266
+ }
267
+ };
268
+ });
269
+ }
270
+ /**
271
+ * Cancel the current stream.
272
+ *
273
+ * Sends a stop message to the server to cancel the ongoing query.
274
+ * This is a best-effort operation - if the connection is already
275
+ * closed or in an invalid state, the cancellation will return
276
+ * a result indicating the failure reason but won't throw an error.
277
+ *
278
+ * @returns Result object with success status and reason
279
+ *
280
+ * @example
281
+ * ```ts
282
+ * const result = streaming.cancel();
283
+ * if (!result.success) {
284
+ * if (result.reason === 'no_active_stream') {
285
+ * console.log('No stream to cancel');
286
+ * } else if (result.reason === 'send_failed') {
287
+ * console.error('Failed to send cancel:', result.error);
288
+ * }
289
+ * }
290
+ * ```
291
+ */
292
+ cancel() {
293
+ if (!this.ws || !this.currentMessageId) {
294
+ return { success: false, reason: 'no_active_stream' };
295
+ }
296
+ try {
297
+ this.ws.send(JSON.stringify({
298
+ type: 'stop',
299
+ message_id: this.currentMessageId,
300
+ }));
301
+ return { success: true, reason: 'sent' };
302
+ }
303
+ catch (err) {
304
+ // Cancellation is best-effort - the WebSocket may already be closed
305
+ const errorMessage = err instanceof Error ? err.message : String(err);
306
+ const context = { messageId: this.currentMessageId, wsReadyState: this.ws?.readyState };
307
+ if (this.onWarning) {
308
+ this.onWarning('Failed to send cancel message', { error: errorMessage, ...context });
309
+ }
310
+ else {
311
+ // prettier-ignore
312
+ console.warn('[AttroveSDK] Failed to send cancel message:', errorMessage, context);
313
+ }
314
+ return { success: false, reason: 'send_failed', error: errorMessage };
315
+ }
316
+ }
317
+ /**
318
+ * Clean up resources.
319
+ *
320
+ * Closes the WebSocket connection and resets internal state.
321
+ * This is called automatically when a stream completes, errors,
322
+ * or is cancelled.
323
+ */
324
+ cleanup() {
325
+ if (this.ws) {
326
+ try {
327
+ this.ws.close(1000);
328
+ }
329
+ catch (err) {
330
+ // Cleanup is best-effort - the WebSocket may already be closed
331
+ const errorMessage = err instanceof Error ? err.message : String(err);
332
+ if (this.onWarning) {
333
+ this.onWarning('Failed to close WebSocket cleanly', { error: errorMessage });
334
+ }
335
+ else {
336
+ // prettier-ignore
337
+ console.warn('[AttroveSDK] Failed to close WebSocket cleanly:', errorMessage);
338
+ }
339
+ }
340
+ this.ws = null;
341
+ }
342
+ this.currentMessageId = null;
343
+ this.onWarning = undefined;
344
+ }
345
+ /**
346
+ * Close the connection.
347
+ *
348
+ * Call this when you're done with the streaming client to ensure
349
+ * all resources are properly cleaned up.
350
+ */
351
+ close() {
352
+ this.cleanup();
353
+ }
354
+ }
355
+ exports.StreamingClient = StreamingClient;
356
+ /**
357
+ * Generate a unique message ID for streaming.
358
+ *
359
+ * Creates a message ID in the format `msg_{timestamp}_{random}` that is
360
+ * sufficiently unique for tracking individual stream requests.
361
+ *
362
+ * @returns A unique message ID string
363
+ */
364
+ function generateMessageId() {
365
+ return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
366
+ }
367
+ exports.generateMessageId = generateMessageId;
368
+ //# sourceMappingURL=streaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../../../../../packages/sdk/src/utils/streaming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * SDK Version Utilities
4
+ *
5
+ * Provides version information for the SDK using a static constant.
6
+ * This ensures browser compatibility while keeping the API consistent.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.resetVersionCache = exports.getVersion = void 0;
10
+ const constants_1 = require("./constants");
11
+ /**
12
+ * Get the SDK version.
13
+ *
14
+ * Returns the SDK version string from the hardcoded constant.
15
+ * This value should be kept in sync with package.json during releases.
16
+ */
17
+ function getVersion() {
18
+ return constants_1.SDK_VERSION;
19
+ }
20
+ exports.getVersion = getVersion;
21
+ /**
22
+ * Reset the cached version.
23
+ *
24
+ * @deprecated This function has no effect. Version is now a static constant.
25
+ * Kept for API compatibility with existing tests.
26
+ */
27
+ function resetVersionCache() {
28
+ // No-op - version is now a static constant
29
+ }
30
+ exports.resetVersionCache = resetVersionCache;
31
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../../../packages/sdk/src/version.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,2CAA0C;AAE1C;;;;;GAKG;AACH,SAAgB,UAAU;IACxB,OAAO,uBAAW,CAAC;AACrB,CAAC;AAFD,gCAEC;AAED;;;;;GAKG;AACH,SAAgB,iBAAiB;IAC/B,2CAA2C;AAC7C,CAAC;AAFD,8CAEC"}
package/esm/README.md ADDED
@@ -0,0 +1,247 @@
1
+ # @attrove/sdk
2
+
3
+ Official TypeScript SDK for the Attrove API. Access AI-powered context from your users' Gmail, Slack, Google Calendar, and more.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @attrove/sdk
9
+ # or
10
+ yarn add @attrove/sdk
11
+ # or
12
+ pnpm add @attrove/sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { Attrove } from '@attrove/sdk';
19
+
20
+ // Create a client
21
+ const attrove = new Attrove({
22
+ apiKey: 'sk_...', // API key from your dashboard
23
+ userId: 'user-uuid' // User ID from provisioning
24
+ });
25
+
26
+ // Query user's context
27
+ const response = await attrove.query('What meetings do I have tomorrow?');
28
+ console.log(response.answer);
29
+
30
+ // Search for specific information
31
+ const results = await attrove.search('quarterly report');
32
+ ```
33
+
34
+ ## Core Methods
35
+
36
+ ### `query(prompt, options?)`
37
+
38
+ Ask questions about the user's unified context with AI-generated answers.
39
+
40
+ ```typescript
41
+ // Simple query
42
+ const response = await attrove.query('What did Sarah say about the Q4 budget?');
43
+ console.log(response.answer);
44
+
45
+ // Multi-turn conversation - pass history from previous response
46
+ let history = response.history;
47
+ const followUp = await attrove.query('What about Q3?', { history });
48
+ // Update history for subsequent queries
49
+ history = followUp.history;
50
+
51
+ // With filters
52
+ const filtered = await attrove.query('Latest updates', {
53
+ integrationIds: ['integration-uuid'], // Only search specific integration
54
+ includeSources: true // Include source snippets
55
+ });
56
+ ```
57
+
58
+ ### `search(query, options?)`
59
+
60
+ Semantic search that returns raw messages without AI summarization.
61
+
62
+ ```typescript
63
+ const results = await attrove.search('product launch', {
64
+ afterDate: '2024-01-01T00:00:00Z',
65
+ senderDomains: ['acme.com'],
66
+ includeBodyText: true
67
+ });
68
+
69
+ for (const [convId, conv] of Object.entries(results.conversations)) {
70
+ console.log(`Conversation: ${conv.conversation_name}`);
71
+ }
72
+ ```
73
+
74
+ ## Resource Namespaces
75
+
76
+ ### Users
77
+
78
+ ```typescript
79
+ // Get user profile and integrations
80
+ const { user, integrations } = await attrove.users.get();
81
+
82
+ // Update user profile
83
+ await attrove.users.update({
84
+ timezone: 'America/New_York'
85
+ });
86
+
87
+ // Get sync statistics
88
+ const stats = await attrove.users.syncStats();
89
+ console.log(`Messages: ${stats.totals.messages.count}`);
90
+ ```
91
+
92
+ ### Messages
93
+
94
+ ```typescript
95
+ // List messages
96
+ const { data, pagination } = await attrove.messages.list({
97
+ limit: 20,
98
+ expand: ['body_text']
99
+ });
100
+
101
+ // Get specific messages (e.g., after a query)
102
+ const { data: messages } = await attrove.messages.list({
103
+ ids: response.used_message_ids,
104
+ expand: ['body_text']
105
+ });
106
+
107
+ // Get a single message by ID
108
+ const message = await attrove.messages.get('message-uuid');
109
+ ```
110
+
111
+ ### Conversations
112
+
113
+ ```typescript
114
+ // List conversations
115
+ const { data: conversations } = await attrove.conversations.list({
116
+ syncedOnly: true
117
+ });
118
+
119
+ // Update sync settings
120
+ await attrove.conversations.updateSync([
121
+ { id: 'conversation-uuid-1', importMessages: true },
122
+ { id: 'conversation-uuid-2', importMessages: false }
123
+ ]);
124
+ ```
125
+
126
+ ### Integrations
127
+
128
+ ```typescript
129
+ // List integrations
130
+ const integrations = await attrove.integrations.list();
131
+
132
+ // Disconnect an integration
133
+ await attrove.integrations.disconnect('integration-uuid');
134
+ ```
135
+
136
+ ## Server-to-Server (Admin) API
137
+
138
+ Use the admin client for operations that require partner authentication:
139
+
140
+ ```typescript
141
+ import { Attrove } from '@attrove/sdk';
142
+
143
+ // Create admin client
144
+ const admin = Attrove.admin({
145
+ clientId: 'your-client-id',
146
+ clientSecret: 'your-client-secret'
147
+ });
148
+
149
+ // Create a user
150
+ const { id, apiKey } = await admin.users.create({
151
+ email: 'user@example.com',
152
+ firstName: 'John',
153
+ lastName: 'Doe'
154
+ });
155
+
156
+ // Generate integration token for OAuth flow
157
+ const { token: connectToken, expires_at } = await admin.users.createConnectToken(id);
158
+
159
+ // Use the apiKey for subsequent API calls
160
+ const attrove = new Attrove({ apiKey, userId: id });
161
+
162
+ // Redirect user to OAuth flow
163
+ // The URL format depends on your deployment - check your dashboard for the exact URL
164
+ // Example: const oauthUrl = `${YOUR_BASE_URL}/connect/gmail?token=${connectToken}`;
165
+ ```
166
+
167
+ ## Error Handling
168
+
169
+ The SDK provides typed errors for better error handling:
170
+
171
+ ```typescript
172
+ import {
173
+ Attrove,
174
+ AttroveError,
175
+ AuthenticationError,
176
+ NotFoundError,
177
+ RateLimitError
178
+ } from '@attrove/sdk';
179
+
180
+ try {
181
+ const response = await attrove.query('...');
182
+ } catch (error) {
183
+ if (error instanceof AuthenticationError) {
184
+ console.log('Invalid API key');
185
+ } else if (error instanceof RateLimitError) {
186
+ console.log(`Rate limited. Retry after ${error.retryAfter}s`);
187
+ } else if (error instanceof NotFoundError) {
188
+ console.log('Resource not found');
189
+ } else if (error instanceof AttroveError) {
190
+ console.log(`Error: ${error.code} - ${error.message}`);
191
+ }
192
+ }
193
+ ```
194
+
195
+ ## Streaming (Advanced)
196
+
197
+ For real-time streaming of query responses:
198
+
199
+ ```typescript
200
+ const result = await attrove.stream('What happened in the meeting?', {
201
+ onChunk: (chunk) => process.stdout.write(chunk),
202
+ onState: (state) => console.log('State:', state),
203
+ onEnd: (reason) => console.log('Stream ended:', reason)
204
+ });
205
+
206
+ console.log('Full answer:', result.answer);
207
+ ```
208
+
209
+ > **Note:** Streaming uses WebSocket connections and requires the same API key authentication as other SDK methods. It is primarily intended for end-user facing applications where progressive display of responses improves the user experience.
210
+
211
+ ## Configuration
212
+
213
+ ```typescript
214
+ const attrove = new Attrove({
215
+ apiKey: 'sk_...', // Required: API key
216
+ userId: 'user-uuid', // Required: User ID
217
+ baseUrl: 'https://api.attrove.com', // Optional: API base URL
218
+ timeout: 30000, // Optional: Request timeout (ms)
219
+ maxRetries: 3 // Optional: Retry attempts
220
+ });
221
+ ```
222
+
223
+ ## TypeScript Support
224
+
225
+ The SDK is fully typed. Import types as needed:
226
+
227
+ ```typescript
228
+ import {
229
+ QueryOptions,
230
+ QueryResponse,
231
+ SearchOptions,
232
+ SearchResponse,
233
+ User,
234
+ Message,
235
+ Integration,
236
+ ConversationMessage
237
+ } from '@attrove/sdk';
238
+ ```
239
+
240
+ ## Requirements
241
+
242
+ - Node.js 18.0.0 or later
243
+ - TypeScript 4.7+ (if using TypeScript)
244
+
245
+ ## License
246
+
247
+ MIT