@trainly/react 1.4.0 → 1.4.1

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
@@ -86,9 +86,58 @@ function MyComponent() {
86
86
  - ✅ **Zero Migration**: Works with your existing OAuth setup
87
87
  - ✅ **Simple Integration**: Just add `appId` and use `connectWithOAuthToken()`
88
88
 
89
- ## 📁 **NEW: File Management**
89
+ ## 🏷️ **NEW: Custom Scopes (Zero Config)**
90
90
 
91
- Now users can manage their uploaded files directly:
91
+ Tag your documents with custom attributes for powerful filtering and organization:
92
+
93
+ ```tsx
94
+ import { useTrainly } from "@trainly/react";
95
+
96
+ function MyApp() {
97
+ const { upload, ask } = useTrainly();
98
+
99
+ // 1. Upload with scopes - use any keys you want!
100
+ await upload(file, {
101
+ playlist_id: "xyz123",
102
+ workspace_id: "acme_corp",
103
+ project: "alpha",
104
+ });
105
+
106
+ // 2. Query with scope filters - only get results from matching documents
107
+ const answer = await ask("What are the key features?", {
108
+ scope_filters: { playlist_id: "xyz123" },
109
+ });
110
+ // ☝️ Only searches documents with playlist_id="xyz123"
111
+
112
+ // Query with multiple filters
113
+ const answer2 = await ask("Show me updates", {
114
+ scope_filters: {
115
+ workspace_id: "acme_corp",
116
+ project: "alpha",
117
+ },
118
+ });
119
+ // ☝️ Only searches documents matching ALL specified scopes
120
+
121
+ // Query everything (no filters)
122
+ const answer3 = await ask("What do I have?");
123
+ // ☝️ Searches ALL user's documents
124
+ }
125
+ ```
126
+
127
+ **No setup required!** Just pass any key-value pairs - perfect for multi-tenant apps, playlist systems, workspace organization, and more.
128
+
129
+ **Use Cases:**
130
+
131
+ - 🎵 **Playlist Apps**: Filter by `playlist_id` to query specific playlists
132
+ - 🏢 **Multi-Tenant SaaS**: Filter by `tenant_id` or `workspace_id`
133
+ - 📁 **Project Management**: Filter by `project_id` or `team_id`
134
+ - 👥 **User Segmentation**: Filter by `user_tier`, `department`, etc.
135
+
136
+ [📖 Full Scopes Guide](./SCOPES_GUIDE.md)
137
+
138
+ ## 📁 **File Management**
139
+
140
+ Users can manage their uploaded files directly:
92
141
 
93
142
  ```tsx
94
143
  import { useTrainly, TrainlyFileManager } from "@trainly/react";
@@ -142,6 +191,67 @@ function MyApp() {
142
191
  - 📋 **List Files**: View all uploaded documents with metadata
143
192
  - 🗑️ **Delete Files**: Remove files and free up storage space
144
193
  - 📊 **Storage Analytics**: Track file sizes and storage usage
194
+
195
+ ## 🏷️ **NEW in v1.4.0: Custom Scopes**
196
+
197
+ Tag your documents with custom attributes for powerful data segmentation!
198
+
199
+ ```tsx
200
+ import { useTrainly } from "@trainly/react";
201
+
202
+ function PlaylistUploader({ playlistId }) {
203
+ const { upload } = useTrainly();
204
+
205
+ const handleUpload = async (file: File) => {
206
+ // Upload with custom scope values
207
+ await upload(file, {
208
+ playlist_id: playlistId,
209
+ user_id: currentUser.id,
210
+ is_public: false,
211
+ });
212
+ };
213
+
214
+ return (
215
+ <input type="file" onChange={(e) => handleUpload(e.target.files[0])} />
216
+ );
217
+ }
218
+ ```
219
+
220
+ ### Scope Features
221
+
222
+ - 🎯 **Data Segmentation**: Keep playlists, workspaces, or projects separate
223
+ - ⚡ **Faster Queries**: Filter at database level before vector search
224
+ - 🔒 **Complete Isolation**: Multi-tenant apps with full data privacy
225
+ - 🎨 **Flexible**: Define any custom attributes you need
226
+
227
+ ### With TrainlyUpload Component
228
+
229
+ ```tsx
230
+ <TrainlyUpload
231
+ variant="drag-drop"
232
+ scopeValues={{
233
+ playlist_id: "playlist_123",
234
+ workspace_id: "workspace_456",
235
+ }}
236
+ onUpload={(files) => console.log("Uploaded with scopes!")}
237
+ />
238
+ ```
239
+
240
+ ### Complete Documentation
241
+
242
+ See **[SCOPES_GUIDE.md](./SCOPES_GUIDE.md)** for:
243
+
244
+ - Complete API reference
245
+ - Real-world examples
246
+ - Advanced patterns
247
+ - Testing & debugging
248
+ - Migration guide
249
+
250
+ **Quick Reference:**
251
+
252
+ - `upload(file, scopeValues)` - Upload with scopes
253
+ - `bulkUploadFiles(files, scopeValues)` - Bulk upload with scopes
254
+ - `<TrainlyUpload scopeValues={{...}} />` - Component with scopes
145
255
  - 🔄 **Auto-Refresh**: File list updates after uploads/deletions
146
256
  - 🎨 **Pre-built UI**: `TrainlyFileManager` component with styling
147
257
  - 🔒 **Privacy-First**: Only works in V1 mode with OAuth authentication
@@ -17,6 +17,7 @@ export declare class TrainlyClient {
17
17
  connect(): Promise<void>;
18
18
  ask(question: string, options?: {
19
19
  includeCitations?: boolean;
20
+ scope_filters?: Record<string, string | number | boolean>;
20
21
  }): Promise<QueryResponse>;
21
22
  upload(file: File, scopeValues?: Record<string, string | number | boolean>): Promise<UploadResult>;
22
23
  bulkUploadFiles(files: File[], scopeValues?: Record<string, string | number | boolean>): Promise<BulkUploadResult>;
@@ -142,7 +142,7 @@ var TrainlyClient = /** @class */ (function () {
142
142
  };
143
143
  TrainlyClient.prototype.ask = function (question_1) {
144
144
  return __awaiter(this, arguments, void 0, function (question, options) {
145
- var response_1, error, data_1, url, headers, body, response, error, data;
145
+ var params, response_1, error, data_1, url, headers, body, response, error, data;
146
146
  if (options === void 0) { options = {}; }
147
147
  return __generator(this, function (_a) {
148
148
  switch (_a.label) {
@@ -151,6 +151,15 @@ var TrainlyClient = /** @class */ (function () {
151
151
  throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
152
152
  }
153
153
  if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
154
+ params = {
155
+ messages: JSON.stringify([{ role: "user", content: question }]),
156
+ response_tokens: "150",
157
+ };
158
+ // Add scope filters if provided
159
+ if (options.scope_filters &&
160
+ Object.keys(options.scope_filters).length > 0) {
161
+ params.scope_filters = JSON.stringify(options.scope_filters);
162
+ }
154
163
  return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/query"), {
155
164
  method: "POST",
156
165
  headers: {
@@ -158,10 +167,7 @@ var TrainlyClient = /** @class */ (function () {
158
167
  "X-App-ID": this.config.appId,
159
168
  "Content-Type": "application/x-www-form-urlencoded",
160
169
  },
161
- body: new URLSearchParams({
162
- messages: JSON.stringify([{ role: "user", content: question }]),
163
- response_tokens: "150",
164
- }),
170
+ body: new URLSearchParams(params),
165
171
  })];
166
172
  case 1:
167
173
  response_1 = _a.sent();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@trainly/react",
3
- "version": "1.4.0",
4
- "description": "Dead simple RAG integration for React apps with OAuth authentication",
3
+ "version": "1.4.1",
4
+ "description": "Dead simple RAG integration for React apps with OAuth authentication and custom scopes",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
@@ -28,7 +28,11 @@
28
28
  "document-chat",
29
29
  "file-management",
30
30
  "file-upload",
31
- "file-deletion"
31
+ "file-deletion",
32
+ "custom-scopes",
33
+ "scope-filtering",
34
+ "data-segmentation",
35
+ "multi-tenant"
32
36
  ],
33
37
  "author": "Trainly",
34
38
  "license": "MIT",