flowstack-sdk 0.2.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.
@@ -0,0 +1,1065 @@
1
+ 'use strict';
2
+
3
+ // src/api/client.ts
4
+ var DEFAULT_BASE_URL = "https://sage-api.flowstack.fun";
5
+ var DEFAULT_TENANT_ID = "";
6
+ async function flowstackFetch(endpoint, options, config) {
7
+ const { method = "GET", body, headers = {}, credentials } = options;
8
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
9
+ const enforceUserScope = config?.enforceUserScope !== false;
10
+ const { apiKey, tenantId, userId } = credentials;
11
+ if (enforceUserScope && !userId) {
12
+ console.error("[FlowstackClient] CRITICAL: No user ID provided!");
13
+ throw new Error("SECURITY: User ID is required for all API requests.");
14
+ }
15
+ const url = new URL(`${baseUrl}${endpoint}`);
16
+ if (method === "GET" && userId) {
17
+ url.searchParams.set("user_id", userId);
18
+ }
19
+ const requestHeaders = {
20
+ "Authorization": `Bearer ${apiKey}`,
21
+ "X-Tenant-ID": tenantId || config?.tenantId || DEFAULT_TENANT_ID,
22
+ "X-User-ID": userId || "",
23
+ ...headers
24
+ };
25
+ if (body && !requestHeaders["Content-Type"]) {
26
+ requestHeaders["Content-Type"] = "application/json";
27
+ }
28
+ try {
29
+ const response = await fetch(url.toString(), {
30
+ method,
31
+ headers: requestHeaders,
32
+ body: body ? JSON.stringify(body) : void 0
33
+ });
34
+ if (!response.ok) {
35
+ const errorText = await response.text();
36
+ console.error(`[FlowstackClient] Error ${response.status}:`, errorText);
37
+ return {
38
+ ok: false,
39
+ status: response.status,
40
+ error: errorText
41
+ };
42
+ }
43
+ const data = await response.json();
44
+ return {
45
+ ok: true,
46
+ status: response.status,
47
+ data
48
+ };
49
+ } catch (error) {
50
+ console.error("[FlowstackClient] Request failed:", error);
51
+ return {
52
+ ok: false,
53
+ status: 500,
54
+ error: error instanceof Error ? error.message : "Unknown error"
55
+ };
56
+ }
57
+ }
58
+ async function listWorkspaces(credentials, limit = 50, config) {
59
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
60
+ return flowstackFetch(`/tenants/${tenantId}/workspaces?limit=${limit}`, {
61
+ credentials
62
+ }, config);
63
+ }
64
+ async function createWorkspace(credentials, name, description, config) {
65
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
66
+ return flowstackFetch(`/tenants/${tenantId}/workspaces`, {
67
+ method: "POST",
68
+ credentials,
69
+ body: {
70
+ name,
71
+ workspace_name: name,
72
+ description,
73
+ user_id: credentials.userId
74
+ }
75
+ }, config);
76
+ }
77
+ async function getWorkspace(credentials, workspaceId, config) {
78
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
79
+ return flowstackFetch(`/tenants/${tenantId}/workspaces/${workspaceId}`, {
80
+ credentials
81
+ }, config);
82
+ }
83
+ async function listDatasets(credentials, workspaceId, config) {
84
+ const query = workspaceId ? `?workspace_id=${workspaceId}&session_id=${workspaceId}` : "";
85
+ return flowstackFetch(`/datasets${query}`, {
86
+ credentials
87
+ }, config);
88
+ }
89
+ async function getDataset(credentials, datasetName, config) {
90
+ return flowstackFetch(`/datasets/${datasetName}/download`, {
91
+ credentials
92
+ }, config);
93
+ }
94
+ async function getDatasetPreview(credentials, datasetName, workspaceId, config) {
95
+ return flowstackFetch(`/datasets/${datasetName}/preview?workspace_id=${workspaceId}&session_id=${workspaceId}&limit=50`, {
96
+ credentials
97
+ }, config);
98
+ }
99
+ async function deleteDataset(_credentials, _datasetName, _config) {
100
+ return {
101
+ ok: false,
102
+ status: 501,
103
+ error: "Dataset deletion is handled through the agent chat interface. Use the /stream endpoint to request deletion."
104
+ };
105
+ }
106
+ async function listVisualizations(credentials, workspaceId, config) {
107
+ return flowstackFetch(`/visualizations?workspace_id=${workspaceId}&session_id=${workspaceId}`, {
108
+ credentials
109
+ }, config);
110
+ }
111
+ async function listReports(credentials, workspaceId, config) {
112
+ return flowstackFetch(`/reports?workspace_id=${workspaceId}&session_id=${workspaceId}`, {
113
+ credentials
114
+ }, config);
115
+ }
116
+ async function listModels(credentials, workspaceId, config) {
117
+ return flowstackFetch(`/models?workspace_id=${workspaceId}&session_id=${workspaceId}`, {
118
+ credentials
119
+ }, config);
120
+ }
121
+ async function getModel(credentials, workspaceId, modelName, config) {
122
+ return flowstackFetch(`/models/${modelName}?workspace_id=${workspaceId}&session_id=${workspaceId}`, {
123
+ credentials
124
+ }, config);
125
+ }
126
+ async function listScripts(credentials, workspaceId, config) {
127
+ return flowstackFetch(`/scripts/detailed?workspace_id=${workspaceId}&session_id=${workspaceId}`, {
128
+ credentials
129
+ }, config);
130
+ }
131
+ async function listDataSources(credentials, config, options) {
132
+ const qs = options?.includeProvenance ? "?include_provenance=true" : "";
133
+ return flowstackFetch(`/data-sources${qs}`, {
134
+ credentials
135
+ }, config);
136
+ }
137
+ async function createDataSource(credentials, sourceConfig, config) {
138
+ return flowstackFetch("/data-sources", {
139
+ method: "POST",
140
+ credentials,
141
+ body: {
142
+ source_type: sourceConfig.type,
143
+ name: sourceConfig.name,
144
+ auth_method: sourceConfig.auth_method || "connection_string",
145
+ credentials: sourceConfig.credentials || {
146
+ connection_string: sourceConfig.connectionString
147
+ },
148
+ metadata: sourceConfig.metadata,
149
+ is_tenant_wide: sourceConfig.is_tenant_wide || false
150
+ }
151
+ }, config);
152
+ }
153
+ async function testDataSource(credentials, sourceId, config) {
154
+ return flowstackFetch(`/data-sources/${sourceId}/test`, {
155
+ method: "POST",
156
+ credentials
157
+ }, config);
158
+ }
159
+ async function deleteDataSource(credentials, sourceId, config) {
160
+ return flowstackFetch(`/data-sources/${sourceId}`, {
161
+ method: "DELETE",
162
+ credentials
163
+ }, config);
164
+ }
165
+ async function listAgents(config) {
166
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
167
+ try {
168
+ const response = await fetch(`${baseUrl}/agents`, {
169
+ method: "GET",
170
+ headers: { "Accept": "application/json" }
171
+ });
172
+ if (!response.ok) {
173
+ const errorText = await response.text();
174
+ return { ok: false, status: response.status, error: errorText };
175
+ }
176
+ const data = await response.json();
177
+ return { ok: true, status: response.status, data };
178
+ } catch (error) {
179
+ return {
180
+ ok: false,
181
+ status: 500,
182
+ error: error instanceof Error ? error.message : "Failed to fetch agents"
183
+ };
184
+ }
185
+ }
186
+ async function executeQuery(credentials, query, workspaceId, options, config) {
187
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
188
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
189
+ const response = await fetch(`${baseUrl}/stream`, {
190
+ method: "POST",
191
+ headers: {
192
+ "Content-Type": "application/json",
193
+ "Authorization": `Bearer ${credentials.apiKey}`,
194
+ "X-Tenant-ID": tenantId,
195
+ "X-User-ID": credentials.userId || "",
196
+ "Accept": "text/event-stream"
197
+ },
198
+ body: JSON.stringify({
199
+ query,
200
+ workspace_id: workspaceId,
201
+ session_id: options?.sessionId || void 0,
202
+ force_new_session: options?.forceNewSession || void 0,
203
+ tenant_id: tenantId,
204
+ user_id: credentials.userId,
205
+ code_interpreter_network_mode: options?.networkMode || "SANDBOX",
206
+ // P0-80: capabilities replaces target_agents on the wire. Deprecated
207
+ // target_agents/target_agent are intentionally NOT forwarded — they
208
+ // were no-ops post-P0-73 and forwarding them just added noise to logs.
209
+ capabilities: options?.capabilities && options.capabilities.length > 0 ? options.capabilities : void 0
210
+ })
211
+ });
212
+ if (!response.ok) {
213
+ if (response.status === 402) {
214
+ let body = {};
215
+ try {
216
+ body = await response.json();
217
+ } catch {
218
+ }
219
+ const err = new Error(body?.message || "Out of credits \u2014 top up to continue");
220
+ err.status = 402;
221
+ err.code = "INSUFFICIENT_CREDITS";
222
+ err.body = body;
223
+ throw err;
224
+ }
225
+ let detail = response.statusText;
226
+ try {
227
+ const body = await response.json();
228
+ detail = body?.detail || body?.error || body?.message || detail;
229
+ } catch {
230
+ }
231
+ throw new Error(`Query failed: ${detail}`);
232
+ }
233
+ return response;
234
+ }
235
+ async function executeQueryWithConfig(credentials, query, workspaceId, options, config) {
236
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
237
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
238
+ const response = await fetch(`${baseUrl}/stream`, {
239
+ method: "POST",
240
+ headers: {
241
+ "Content-Type": "application/json",
242
+ "Authorization": `Bearer ${credentials.apiKey}`,
243
+ "X-Tenant-ID": tenantId,
244
+ "X-User-ID": credentials.userId || "",
245
+ "Accept": "text/event-stream"
246
+ },
247
+ body: JSON.stringify({
248
+ query,
249
+ workspace_id: workspaceId,
250
+ session_id: options?.sessionId || void 0,
251
+ force_new_session: options?.forceNewSession || void 0,
252
+ tenant_id: tenantId,
253
+ user_id: credentials.userId,
254
+ code_interpreter_network_mode: options?.networkMode || "SANDBOX",
255
+ // P0-80: capabilities replaces target_agents on the wire.
256
+ capabilities: options?.capabilities && options.capabilities.length > 0 ? options.capabilities : void 0,
257
+ system_prompt_override: options?.systemPrompt,
258
+ tool_whitelist: options?.tools,
259
+ allowed_terms: options?.allowedTerms || void 0,
260
+ // P0-132 (G4): persona selection → target_agents. The backend persona
261
+ // resolver honors request.target_agents and otherwise auto-selects the
262
+ // first registered subagent. Only sent when a persona is requested.
263
+ target_agents: options?.persona ? [options.persona] : void 0
264
+ })
265
+ });
266
+ if (!response.ok) {
267
+ throw new Error(`Query failed: ${response.statusText}`);
268
+ }
269
+ return response;
270
+ }
271
+ async function queryCollection(credentials, collection, options, config) {
272
+ const params = new URLSearchParams();
273
+ params.set("collection", collection);
274
+ if (options?.filter) params.set("filter", JSON.stringify(options.filter));
275
+ if (options?.limit) params.set("limit", String(options.limit));
276
+ if (options?.skip) params.set("skip", String(options.skip));
277
+ if (options?.sort) params.set("sort", JSON.stringify(options.sort));
278
+ if (options?.projection) params.set("projection", JSON.stringify(options.projection));
279
+ if (options?.layer) params.set("layer", options.layer);
280
+ if (options?.includeProvenance) params.set("include_provenance", "true");
281
+ return flowstackFetch(
282
+ `/collections/query?${params.toString()}`,
283
+ { credentials },
284
+ config
285
+ );
286
+ }
287
+ async function insertDocuments(credentials, collection, documents, config, layer) {
288
+ const isArray = Array.isArray(documents);
289
+ return flowstackFetch(
290
+ "/collections/insert",
291
+ {
292
+ method: "POST",
293
+ credentials,
294
+ body: {
295
+ collection,
296
+ ...isArray ? { documents } : { document: documents },
297
+ ...layer ? { layer } : {}
298
+ }
299
+ },
300
+ config
301
+ );
302
+ }
303
+ async function updateDocuments(credentials, collection, filter, update, options, config, layer) {
304
+ return flowstackFetch(
305
+ "/collections/update",
306
+ {
307
+ method: "POST",
308
+ credentials,
309
+ body: {
310
+ collection,
311
+ filter,
312
+ update,
313
+ upsert: options?.upsert ?? false,
314
+ ...layer ? { layer } : {}
315
+ }
316
+ },
317
+ config
318
+ );
319
+ }
320
+ async function deleteDocuments(credentials, collection, filter, config, layer) {
321
+ return flowstackFetch(
322
+ "/collections/delete",
323
+ {
324
+ method: "POST",
325
+ credentials,
326
+ body: {
327
+ collection,
328
+ filter,
329
+ ...layer ? { layer } : {}
330
+ }
331
+ },
332
+ config
333
+ );
334
+ }
335
+ async function invokeTool(credentials, agentName, toolName, kwargs = {}, config) {
336
+ return flowstackFetch(
337
+ "/tool/invoke",
338
+ {
339
+ method: "POST",
340
+ credentials,
341
+ body: {
342
+ agent_name: agentName,
343
+ tool_name: toolName,
344
+ kwargs
345
+ }
346
+ },
347
+ config
348
+ );
349
+ }
350
+ async function uploadFile(credentials, workspaceId, file, name, config) {
351
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
352
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
353
+ const formData = new FormData();
354
+ formData.append("file", file);
355
+ formData.append("workspace_id", workspaceId);
356
+ if (name) {
357
+ formData.append("name", name);
358
+ formData.append("dataset_name", name);
359
+ }
360
+ try {
361
+ const response = await fetch(`${baseUrl}/upload`, {
362
+ method: "POST",
363
+ headers: {
364
+ "Authorization": `Bearer ${credentials.apiKey}`,
365
+ "X-Tenant-ID": tenantId,
366
+ "X-User-ID": credentials.userId || "",
367
+ "X-Session-ID": workspaceId
368
+ },
369
+ body: formData
370
+ });
371
+ if (!response.ok) {
372
+ const errorText = await response.text();
373
+ return {
374
+ ok: false,
375
+ status: response.status,
376
+ error: errorText
377
+ };
378
+ }
379
+ const data = await response.json();
380
+ return {
381
+ ok: true,
382
+ status: response.status,
383
+ data
384
+ };
385
+ } catch (error) {
386
+ return {
387
+ ok: false,
388
+ status: 500,
389
+ error: error instanceof Error ? error.message : "Upload failed"
390
+ };
391
+ }
392
+ }
393
+ async function uploadDocument(credentials, workspaceId, file, documentName, config) {
394
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
395
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
396
+ const formData = new FormData();
397
+ formData.append("file", file);
398
+ formData.append("workspace_id", workspaceId);
399
+ if (documentName) formData.append("document_name", documentName);
400
+ try {
401
+ const response = await fetch(`${baseUrl}/upload-document`, {
402
+ method: "POST",
403
+ headers: {
404
+ "Authorization": `Bearer ${credentials.apiKey}`,
405
+ "X-Tenant-ID": tenantId,
406
+ "X-User-ID": credentials.userId || "",
407
+ "X-Session-ID": workspaceId
408
+ },
409
+ body: formData
410
+ });
411
+ if (!response.ok) {
412
+ const errorText = await response.text();
413
+ return { ok: false, status: response.status, error: errorText };
414
+ }
415
+ const data = await response.json();
416
+ return { ok: true, status: response.status, data };
417
+ } catch (error) {
418
+ return {
419
+ ok: false,
420
+ status: 500,
421
+ error: error instanceof Error ? error.message : "Document upload failed"
422
+ };
423
+ }
424
+ }
425
+ async function login(email, password, config) {
426
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
427
+ try {
428
+ const response = await fetch(`${baseUrl}/auth/user/login`, {
429
+ method: "POST",
430
+ headers: {
431
+ "Content-Type": "application/json",
432
+ ...config?.tenantId ? { "X-Tenant-ID": config.tenantId } : {}
433
+ },
434
+ body: JSON.stringify({
435
+ email,
436
+ password,
437
+ ...config?.appScope ? { app_scope: config.appScope } : {}
438
+ })
439
+ });
440
+ if (!response.ok) {
441
+ const errorText = await response.text();
442
+ return {
443
+ ok: false,
444
+ status: response.status,
445
+ error: errorText
446
+ };
447
+ }
448
+ const data = await response.json();
449
+ return {
450
+ ok: true,
451
+ status: response.status,
452
+ data
453
+ };
454
+ } catch (error) {
455
+ return {
456
+ ok: false,
457
+ status: 500,
458
+ error: error instanceof Error ? error.message : "Login failed"
459
+ };
460
+ }
461
+ }
462
+ async function register(email, password, config) {
463
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
464
+ try {
465
+ const response = await fetch(`${baseUrl}/auth/user/register`, {
466
+ method: "POST",
467
+ headers: {
468
+ "Content-Type": "application/json",
469
+ ...config?.tenantId ? { "X-Tenant-ID": config.tenantId } : {}
470
+ },
471
+ body: JSON.stringify({
472
+ email,
473
+ password,
474
+ skip_email_verification: true,
475
+ ...config?.appScope ? { app_scope: config.appScope } : {}
476
+ })
477
+ });
478
+ if (!response.ok) {
479
+ const errorText = await response.text();
480
+ return {
481
+ ok: false,
482
+ status: response.status,
483
+ error: errorText
484
+ };
485
+ }
486
+ const data = await response.json();
487
+ return {
488
+ ok: true,
489
+ status: response.status,
490
+ data
491
+ };
492
+ } catch (error) {
493
+ return {
494
+ ok: false,
495
+ status: 500,
496
+ error: error instanceof Error ? error.message : "Registration failed"
497
+ };
498
+ }
499
+ }
500
+ async function googleLogin(code, redirectUri, config) {
501
+ const baseUrl = config?.baseUrl || DEFAULT_BASE_URL;
502
+ try {
503
+ const response = await fetch(`${baseUrl}/auth/google/login`, {
504
+ method: "POST",
505
+ headers: {
506
+ "Content-Type": "application/json",
507
+ ...config?.tenantId ? { "X-Tenant-ID": config.tenantId } : {}
508
+ },
509
+ body: JSON.stringify({ code, redirect_uri: redirectUri })
510
+ });
511
+ if (!response.ok) {
512
+ const errorText = await response.text();
513
+ return {
514
+ ok: false,
515
+ status: response.status,
516
+ error: errorText
517
+ };
518
+ }
519
+ const data = await response.json();
520
+ return {
521
+ ok: true,
522
+ status: response.status,
523
+ data
524
+ };
525
+ } catch (error) {
526
+ return {
527
+ ok: false,
528
+ status: 500,
529
+ error: error instanceof Error ? error.message : "Google login failed"
530
+ };
531
+ }
532
+ }
533
+ async function listUsers(credentials, params, config) {
534
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
535
+ const queryParams = new URLSearchParams();
536
+ if (params?.page) queryParams.set("page", String(params.page));
537
+ if (params?.limit) queryParams.set("limit", String(params.limit));
538
+ if (params?.search) queryParams.set("search", params.search);
539
+ if (params?.role) queryParams.set("role", params.role);
540
+ if (params?.status) queryParams.set("status", params.status);
541
+ if (params?.sortBy) queryParams.set("sort_by", params.sortBy);
542
+ if (params?.sortOrder) queryParams.set("sort_order", params.sortOrder);
543
+ const queryString = queryParams.toString();
544
+ const endpoint = `/tenants/${tenantId}/users${queryString ? `?${queryString}` : ""}`;
545
+ return flowstackFetch(endpoint, { credentials }, config);
546
+ }
547
+ async function getUser(credentials, userId, config) {
548
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
549
+ return flowstackFetch(`/tenants/${tenantId}/users/${userId}`, { credentials }, config);
550
+ }
551
+ async function updateUser(credentials, userId, updates, config) {
552
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
553
+ return flowstackFetch(`/tenants/${tenantId}/users/${userId}`, {
554
+ method: "PATCH",
555
+ credentials,
556
+ body: updates
557
+ }, config);
558
+ }
559
+ async function deleteUser(credentials, userId, config) {
560
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
561
+ return flowstackFetch(`/tenants/${tenantId}/users/${userId}`, {
562
+ method: "DELETE",
563
+ credentials
564
+ }, config);
565
+ }
566
+ async function suspendUser(credentials, userId, reason, config) {
567
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
568
+ return flowstackFetch(`/tenants/${tenantId}/users/${userId}/suspend`, {
569
+ method: "POST",
570
+ credentials,
571
+ body: reason ? { reason } : void 0
572
+ }, config);
573
+ }
574
+ async function reactivateUser(credentials, userId, config) {
575
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
576
+ return flowstackFetch(`/tenants/${tenantId}/users/${userId}/reactivate`, {
577
+ method: "POST",
578
+ credentials
579
+ }, config);
580
+ }
581
+ async function getUserActivity(credentials, userId, limit = 50, config) {
582
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
583
+ return flowstackFetch(`/tenants/${tenantId}/users/${userId}/activity?limit=${limit}`, {
584
+ credentials
585
+ }, config);
586
+ }
587
+ async function getUserStats(credentials, config) {
588
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
589
+ return flowstackFetch(`/tenants/${tenantId}/users/stats`, { credentials }, config);
590
+ }
591
+ async function checkAdminPermissions(credentials, config) {
592
+ const tenantId = credentials.tenantId || config?.tenantId || DEFAULT_TENANT_ID;
593
+ return flowstackFetch(`/tenants/${tenantId}/users/me/permissions`, { credentials }, config);
594
+ }
595
+ async function getConversationHistory(credentials, workspaceId, options, config) {
596
+ const params = new URLSearchParams();
597
+ params.set("session_id", workspaceId);
598
+ if (options?.limit) params.set("limit", String(options.limit));
599
+ if (options?.offset) params.set("offset", String(options.offset));
600
+ return flowstackFetch(
601
+ `/conversations?${params.toString()}`,
602
+ { method: "GET", credentials },
603
+ config
604
+ );
605
+ }
606
+ async function listSites(credentials, config) {
607
+ return flowstackFetch("/api/v1/sites", { method: "GET", credentials }, config);
608
+ }
609
+ async function getSite(credentials, siteId, config) {
610
+ return flowstackFetch(`/api/v1/sites/${siteId}`, { method: "GET", credentials }, config);
611
+ }
612
+ async function createSite(credentials, params, config) {
613
+ return flowstackFetch("/api/v1/sites", {
614
+ method: "POST",
615
+ credentials,
616
+ body: {
617
+ site_name: params.name,
618
+ site_type: params.siteType || "on_demand",
619
+ description: params.description,
620
+ files: params.files
621
+ }
622
+ }, config);
623
+ }
624
+ async function addSiteFile(credentials, siteId, filePath, content, config) {
625
+ return flowstackFetch(`/api/v1/sites/${siteId}/files/${filePath}`, {
626
+ method: "PUT",
627
+ credentials,
628
+ body: { content }
629
+ }, config);
630
+ }
631
+ async function publishStagedSite(credentials, siteId, config) {
632
+ return flowstackFetch(`/api/v1/sites/${siteId}/publish`, {
633
+ method: "POST",
634
+ credentials
635
+ }, config);
636
+ }
637
+ async function deleteSite(credentials, siteId, config) {
638
+ return flowstackFetch(`/api/v1/sites/${siteId}`, {
639
+ method: "DELETE",
640
+ credentials
641
+ }, config);
642
+ }
643
+ async function getSiteVersions(credentials, siteId, config) {
644
+ return flowstackFetch(`/api/v1/sites/${siteId}/versions`, {
645
+ method: "GET",
646
+ credentials
647
+ }, config);
648
+ }
649
+ async function promoteSiteVersion(credentials, siteId, version, config) {
650
+ return flowstackFetch(`/api/v1/sites/${siteId}/promote`, {
651
+ method: "POST",
652
+ credentials,
653
+ body: { version }
654
+ }, config);
655
+ }
656
+ async function deleteSiteVersion(credentials, siteId, version, config) {
657
+ return flowstackFetch(`/api/v1/sites/${siteId}/versions/${version}`, {
658
+ method: "DELETE",
659
+ credentials
660
+ }, config);
661
+ }
662
+ async function setSiteAlias(credentials, siteId, alias, config) {
663
+ return flowstackFetch(`/api/v1/sites/${siteId}/alias`, {
664
+ method: "POST",
665
+ credentials,
666
+ body: { alias }
667
+ }, config);
668
+ }
669
+ async function removeSiteAlias(credentials, siteId, config) {
670
+ return flowstackFetch(`/api/v1/sites/${siteId}/alias`, {
671
+ method: "DELETE",
672
+ credentials
673
+ }, config);
674
+ }
675
+ async function publishToGitHub(credentials, siteId, params, config) {
676
+ return flowstackFetch(`/api/v1/sites/${siteId}/publish-github`, {
677
+ method: "POST",
678
+ credentials,
679
+ body: {
680
+ repo_name: params.repoName,
681
+ private: params.isPrivate ?? true,
682
+ ...params.version != null ? { version: params.version } : {}
683
+ }
684
+ }, config);
685
+ }
686
+ async function listGitHubRepos(credentials, config) {
687
+ return flowstackFetch("/api/v1/github/repos", {
688
+ credentials
689
+ }, config);
690
+ }
691
+ async function importFromGitHub(credentials, params, config) {
692
+ return flowstackFetch("/api/v1/github/import", {
693
+ method: "POST",
694
+ credentials,
695
+ body: params
696
+ }, config);
697
+ }
698
+ async function getPiiSettings(credentials, workspaceId, config) {
699
+ return flowstackFetch(`/api/v1/workspaces/${workspaceId}/pii-settings`, {
700
+ credentials
701
+ }, config);
702
+ }
703
+ async function updatePiiSettings(credentials, workspaceId, settings, config) {
704
+ return flowstackFetch(`/api/v1/workspaces/${workspaceId}/pii-settings`, {
705
+ method: "PUT",
706
+ credentials,
707
+ body: settings
708
+ }, config);
709
+ }
710
+ async function previewPiiMasking(credentials, query, config) {
711
+ if (!credentials?.apiKey || credentials.apiKey.split(".").length !== 3) {
712
+ return { ok: false, error: "Not authenticated", status: 401 };
713
+ }
714
+ return flowstackFetch("/stream/pii-preview", {
715
+ method: "POST",
716
+ credentials,
717
+ body: { query }
718
+ }, config);
719
+ }
720
+ async function getPiiAllowlist(credentials, workspaceId, config) {
721
+ return flowstackFetch(`/api/v1/workspaces/${workspaceId}/pii-allowlist`, {
722
+ credentials
723
+ }, config);
724
+ }
725
+ async function addPiiAllowlistTerm(credentials, workspaceId, term, entityType, config) {
726
+ return flowstackFetch(`/api/v1/workspaces/${workspaceId}/pii-allowlist`, {
727
+ method: "POST",
728
+ credentials,
729
+ body: { term, entity_type: entityType }
730
+ }, config);
731
+ }
732
+ async function removePiiAllowlistTerm(credentials, workspaceId, term, config) {
733
+ return flowstackFetch(`/api/v1/workspaces/${workspaceId}/pii-allowlist`, {
734
+ method: "DELETE",
735
+ credentials,
736
+ body: { term }
737
+ }, config);
738
+ }
739
+ async function getUserDataOverview(credentials, config) {
740
+ return flowstackFetch("/api/v1/user/data-overview", {
741
+ credentials
742
+ }, config);
743
+ }
744
+ async function getUserCollections(credentials, params, config) {
745
+ const query = new URLSearchParams();
746
+ if (params?.siteId) query.set("site_id", params.siteId);
747
+ if (params?.includeSchema) query.set("include_schema", "true");
748
+ const qs = query.toString();
749
+ return flowstackFetch(`/api/v1/user/collections${qs ? `?${qs}` : ""}`, {
750
+ credentials
751
+ }, config);
752
+ }
753
+ async function getUserCollectionDocuments(credentials, collection, params, config) {
754
+ const query = new URLSearchParams();
755
+ if (params?.filter) query.set("filter", JSON.stringify(params.filter));
756
+ if (params?.limit != null) query.set("limit", String(params.limit));
757
+ if (params?.skip != null) query.set("skip", String(params.skip));
758
+ if (params?.sort) query.set("sort", JSON.stringify(params.sort));
759
+ if (params?.database) query.set("database", params.database);
760
+ const qs = query.toString();
761
+ return flowstackFetch(`/api/v1/user/collections/${encodeURIComponent(collection)}/documents${qs ? `?${qs}` : ""}`, {
762
+ credentials
763
+ }, config);
764
+ }
765
+ async function getUserCollectionSchema(credentials, collection, params, config) {
766
+ const query = new URLSearchParams();
767
+ if (params?.database) query.set("database", params.database);
768
+ if (params?.sampleSize != null) query.set("sample_size", String(params.sampleSize));
769
+ const qs = query.toString();
770
+ return flowstackFetch(`/api/v1/user/collections/${encodeURIComponent(collection)}/schema${qs ? `?${qs}` : ""}`, {
771
+ credentials
772
+ }, config);
773
+ }
774
+ async function deleteUserCollection(credentials, collection, config) {
775
+ return flowstackFetch(`/api/v1/user/collections/${encodeURIComponent(collection)}?confirm=true`, {
776
+ method: "DELETE",
777
+ credentials
778
+ }, config);
779
+ }
780
+ async function exportUserCollection(credentials, collection, params, config) {
781
+ const query = new URLSearchParams();
782
+ if (params?.database) query.set("database", params.database);
783
+ const qs = query.toString();
784
+ return flowstackFetch(`/api/v1/user/collections/${encodeURIComponent(collection)}/export${qs ? `?${qs}` : ""}`, {
785
+ method: "POST",
786
+ credentials,
787
+ body: {
788
+ format: params?.format || "json",
789
+ filter: params?.filter || null
790
+ }
791
+ }, config);
792
+ }
793
+
794
+ // src/api/cache.ts
795
+ var CACHE_TTL = {
796
+ WORKSPACES: 300,
797
+ // 5 minutes
798
+ DATASETS: 60,
799
+ // 1 minute
800
+ VISUALIZATIONS: 60,
801
+ // 1 minute
802
+ REPORTS: 60,
803
+ // 1 minute
804
+ SITES: 120,
805
+ // 2 minutes
806
+ MESSAGES: 0,
807
+ // No expiry
808
+ SESSION: 86400
809
+ // 24 hours
810
+ };
811
+ var NAMESPACE = "flowstack";
812
+ function createRedisClient(config) {
813
+ const { url, token } = config;
814
+ return {
815
+ async get(key) {
816
+ try {
817
+ const response = await fetch(`${url}/get/${key}`, {
818
+ headers: { Authorization: `Bearer ${token}` }
819
+ });
820
+ if (!response.ok) return null;
821
+ const data = await response.json();
822
+ return data.result ? JSON.parse(data.result) : null;
823
+ } catch {
824
+ return null;
825
+ }
826
+ },
827
+ async set(key, value, ttl) {
828
+ try {
829
+ const body = ttl ? ["SET", key, JSON.stringify(value), "EX", ttl.toString()] : ["SET", key, JSON.stringify(value)];
830
+ const response = await fetch(url, {
831
+ method: "POST",
832
+ headers: {
833
+ Authorization: `Bearer ${token}`,
834
+ "Content-Type": "application/json"
835
+ },
836
+ body: JSON.stringify(body)
837
+ });
838
+ return response.ok;
839
+ } catch {
840
+ return false;
841
+ }
842
+ },
843
+ async del(key) {
844
+ try {
845
+ const response = await fetch(`${url}/del/${key}`, {
846
+ method: "POST",
847
+ headers: { Authorization: `Bearer ${token}` }
848
+ });
849
+ return response.ok;
850
+ } catch {
851
+ return false;
852
+ }
853
+ },
854
+ async keys(pattern) {
855
+ try {
856
+ const response = await fetch(`${url}/keys/${pattern}`, {
857
+ headers: { Authorization: `Bearer ${token}` }
858
+ });
859
+ if (!response.ok) return [];
860
+ const data = await response.json();
861
+ return data.result || [];
862
+ } catch {
863
+ return [];
864
+ }
865
+ }
866
+ };
867
+ }
868
+ function getCacheKey(type, credentials, ...parts) {
869
+ const userId = credentials.userId || "anonymous";
870
+ const tenantId = credentials.tenantId;
871
+ const key = [NAMESPACE, type, tenantId, userId, ...parts].filter(Boolean).join(":");
872
+ return key;
873
+ }
874
+ async function getCachedWorkspaces(credentials, config) {
875
+ const client = createRedisClient(config);
876
+ const key = getCacheKey("workspaces", credentials);
877
+ return client.get(key);
878
+ }
879
+ async function setCachedWorkspaces(credentials, workspaces, config) {
880
+ const client = createRedisClient(config);
881
+ const key = getCacheKey("workspaces", credentials);
882
+ return client.set(key, workspaces, CACHE_TTL.WORKSPACES);
883
+ }
884
+ async function invalidateWorkspacesCache(credentials, config) {
885
+ const client = createRedisClient(config);
886
+ const key = getCacheKey("workspaces", credentials);
887
+ return client.del(key);
888
+ }
889
+ async function getCachedDatasets(credentials, workspaceId, config) {
890
+ const client = createRedisClient(config);
891
+ const key = getCacheKey("datasets", credentials, workspaceId);
892
+ return client.get(key);
893
+ }
894
+ async function setCachedDatasets(credentials, workspaceId, datasets, config) {
895
+ const client = createRedisClient(config);
896
+ const key = getCacheKey("datasets", credentials, workspaceId);
897
+ return client.set(key, datasets, CACHE_TTL.DATASETS);
898
+ }
899
+ async function invalidateDatasetsCache(credentials, workspaceId, config) {
900
+ const client = createRedisClient(config);
901
+ const key = getCacheKey("datasets", credentials, workspaceId);
902
+ return client.del(key);
903
+ }
904
+ async function getCachedVisualizations(credentials, workspaceId, config) {
905
+ const client = createRedisClient(config);
906
+ const key = getCacheKey("visualizations", credentials, workspaceId);
907
+ return client.get(key);
908
+ }
909
+ async function setCachedVisualizations(credentials, workspaceId, visualizations, config) {
910
+ const client = createRedisClient(config);
911
+ const key = getCacheKey("visualizations", credentials, workspaceId);
912
+ return client.set(key, visualizations, CACHE_TTL.VISUALIZATIONS);
913
+ }
914
+ async function invalidateVisualizationsCache(credentials, workspaceId, config) {
915
+ const client = createRedisClient(config);
916
+ const key = getCacheKey("visualizations", credentials, workspaceId);
917
+ return client.del(key);
918
+ }
919
+ async function getCachedReports(credentials, workspaceId, config) {
920
+ const client = createRedisClient(config);
921
+ const key = getCacheKey("reports", credentials, workspaceId);
922
+ return client.get(key);
923
+ }
924
+ async function setCachedReports(credentials, workspaceId, reports, config) {
925
+ const client = createRedisClient(config);
926
+ const key = getCacheKey("reports", credentials, workspaceId);
927
+ return client.set(key, reports, CACHE_TTL.REPORTS);
928
+ }
929
+ async function invalidateReportsCache(credentials, workspaceId, config) {
930
+ const client = createRedisClient(config);
931
+ const key = getCacheKey("reports", credentials, workspaceId);
932
+ return client.del(key);
933
+ }
934
+ async function invalidateWorkspaceArtifacts(credentials, workspaceId, config) {
935
+ await Promise.all([
936
+ invalidateDatasetsCache(credentials, workspaceId, config),
937
+ invalidateVisualizationsCache(credentials, workspaceId, config),
938
+ invalidateReportsCache(credentials, workspaceId, config)
939
+ ]);
940
+ }
941
+ async function invalidateAllUserCache(credentials, config) {
942
+ const client = createRedisClient(config);
943
+ const userId = credentials.userId || "anonymous";
944
+ const tenantId = credentials.tenantId;
945
+ const pattern = `${NAMESPACE}:*:${tenantId}:${userId}:*`;
946
+ const keys = await client.keys(pattern);
947
+ await Promise.all(keys.map((key) => client.del(key)));
948
+ }
949
+ async function getCached(key, config) {
950
+ const client = createRedisClient(config);
951
+ return client.get(`${NAMESPACE}:${key}`);
952
+ }
953
+ async function setCached(key, value, ttl, config) {
954
+ const client = createRedisClient(config);
955
+ return client.set(`${NAMESPACE}:${key}`, value, ttl);
956
+ }
957
+ async function deleteCached(key, config) {
958
+ const client = createRedisClient(config);
959
+ return client.del(`${NAMESPACE}:${key}`);
960
+ }
961
+ async function getCachedSites(credentials, config) {
962
+ const client = createRedisClient(config);
963
+ const key = getCacheKey("sites", credentials);
964
+ return client.get(key);
965
+ }
966
+ async function setCachedSites(credentials, sites, config) {
967
+ const client = createRedisClient(config);
968
+ const key = getCacheKey("sites", credentials);
969
+ return client.set(key, sites, CACHE_TTL.SITES);
970
+ }
971
+ async function invalidateSitesCache(credentials, config) {
972
+ const client = createRedisClient(config);
973
+ const key = getCacheKey("sites", credentials);
974
+ return client.del(key);
975
+ }
976
+
977
+ exports.CACHE_TTL = CACHE_TTL;
978
+ exports.addPiiAllowlistTerm = addPiiAllowlistTerm;
979
+ exports.addSiteFile = addSiteFile;
980
+ exports.checkAdminPermissions = checkAdminPermissions;
981
+ exports.createDataSource = createDataSource;
982
+ exports.createSite = createSite;
983
+ exports.createWorkspace = createWorkspace;
984
+ exports.deleteCached = deleteCached;
985
+ exports.deleteDataSource = deleteDataSource;
986
+ exports.deleteDataset = deleteDataset;
987
+ exports.deleteDocuments = deleteDocuments;
988
+ exports.deleteSite = deleteSite;
989
+ exports.deleteSiteVersion = deleteSiteVersion;
990
+ exports.deleteUser = deleteUser;
991
+ exports.deleteUserCollection = deleteUserCollection;
992
+ exports.executeQuery = executeQuery;
993
+ exports.executeQueryWithConfig = executeQueryWithConfig;
994
+ exports.exportUserCollection = exportUserCollection;
995
+ exports.flowstackFetch = flowstackFetch;
996
+ exports.getCached = getCached;
997
+ exports.getCachedDatasets = getCachedDatasets;
998
+ exports.getCachedReports = getCachedReports;
999
+ exports.getCachedSites = getCachedSites;
1000
+ exports.getCachedVisualizations = getCachedVisualizations;
1001
+ exports.getCachedWorkspaces = getCachedWorkspaces;
1002
+ exports.getConversationHistory = getConversationHistory;
1003
+ exports.getDataset = getDataset;
1004
+ exports.getDatasetPreview = getDatasetPreview;
1005
+ exports.getModel = getModel;
1006
+ exports.getPiiAllowlist = getPiiAllowlist;
1007
+ exports.getPiiSettings = getPiiSettings;
1008
+ exports.getSite = getSite;
1009
+ exports.getSiteVersions = getSiteVersions;
1010
+ exports.getUser = getUser;
1011
+ exports.getUserActivity = getUserActivity;
1012
+ exports.getUserCollectionDocuments = getUserCollectionDocuments;
1013
+ exports.getUserCollectionSchema = getUserCollectionSchema;
1014
+ exports.getUserCollections = getUserCollections;
1015
+ exports.getUserDataOverview = getUserDataOverview;
1016
+ exports.getUserStats = getUserStats;
1017
+ exports.getWorkspace = getWorkspace;
1018
+ exports.googleLogin = googleLogin;
1019
+ exports.importFromGitHub = importFromGitHub;
1020
+ exports.insertDocuments = insertDocuments;
1021
+ exports.invalidateAllUserCache = invalidateAllUserCache;
1022
+ exports.invalidateDatasetsCache = invalidateDatasetsCache;
1023
+ exports.invalidateReportsCache = invalidateReportsCache;
1024
+ exports.invalidateSitesCache = invalidateSitesCache;
1025
+ exports.invalidateVisualizationsCache = invalidateVisualizationsCache;
1026
+ exports.invalidateWorkspaceArtifacts = invalidateWorkspaceArtifacts;
1027
+ exports.invalidateWorkspacesCache = invalidateWorkspacesCache;
1028
+ exports.invokeTool = invokeTool;
1029
+ exports.listAgents = listAgents;
1030
+ exports.listDataSources = listDataSources;
1031
+ exports.listDatasets = listDatasets;
1032
+ exports.listGitHubRepos = listGitHubRepos;
1033
+ exports.listModels = listModels;
1034
+ exports.listReports = listReports;
1035
+ exports.listScripts = listScripts;
1036
+ exports.listSites = listSites;
1037
+ exports.listUsers = listUsers;
1038
+ exports.listVisualizations = listVisualizations;
1039
+ exports.listWorkspaces = listWorkspaces;
1040
+ exports.login = login;
1041
+ exports.previewPiiMasking = previewPiiMasking;
1042
+ exports.promoteSiteVersion = promoteSiteVersion;
1043
+ exports.publishStagedSite = publishStagedSite;
1044
+ exports.publishToGitHub = publishToGitHub;
1045
+ exports.queryCollection = queryCollection;
1046
+ exports.reactivateUser = reactivateUser;
1047
+ exports.register = register;
1048
+ exports.removePiiAllowlistTerm = removePiiAllowlistTerm;
1049
+ exports.removeSiteAlias = removeSiteAlias;
1050
+ exports.setCached = setCached;
1051
+ exports.setCachedDatasets = setCachedDatasets;
1052
+ exports.setCachedReports = setCachedReports;
1053
+ exports.setCachedSites = setCachedSites;
1054
+ exports.setCachedVisualizations = setCachedVisualizations;
1055
+ exports.setCachedWorkspaces = setCachedWorkspaces;
1056
+ exports.setSiteAlias = setSiteAlias;
1057
+ exports.suspendUser = suspendUser;
1058
+ exports.testDataSource = testDataSource;
1059
+ exports.updateDocuments = updateDocuments;
1060
+ exports.updatePiiSettings = updatePiiSettings;
1061
+ exports.updateUser = updateUser;
1062
+ exports.uploadDocument = uploadDocument;
1063
+ exports.uploadFile = uploadFile;
1064
+ //# sourceMappingURL=index.js.map
1065
+ //# sourceMappingURL=index.js.map