@sybil-studio-devs/sdk 0.1.0 → 0.2.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.
@@ -0,0 +1,2354 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/react/index.ts
21
+ var react_exports = {};
22
+ __export(react_exports, {
23
+ SybilAtlas: () => SybilAtlas,
24
+ SybilNexus: () => SybilNexus,
25
+ SybilPages: () => SybilPages,
26
+ useAtlas: () => useAtlas,
27
+ useNexus: () => useNexus,
28
+ useSybilPages: () => useSybilPages
29
+ });
30
+ module.exports = __toCommonJS(react_exports);
31
+
32
+ // src/react/SybilPages.tsx
33
+ var import_react = require("react");
34
+
35
+ // src/client.ts
36
+ var DEFAULT_BASE_URL = "https://app.sybil.studio/api/sdk/v1";
37
+ var DEFAULT_TIMEOUT = 3e4;
38
+ var SybilSDK = class {
39
+ constructor(config) {
40
+ if (typeof config === "string") {
41
+ this.apiKey = config;
42
+ this.baseUrl = DEFAULT_BASE_URL;
43
+ this.timeout = DEFAULT_TIMEOUT;
44
+ } else {
45
+ this.apiKey = config.apiKey;
46
+ this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
47
+ this.timeout = config.timeout || DEFAULT_TIMEOUT;
48
+ }
49
+ if (!this.apiKey) {
50
+ throw new Error("API key is required");
51
+ }
52
+ if (!this.apiKey.startsWith("sk_live_") && !this.apiKey.startsWith("sk_test_")) {
53
+ throw new Error("Invalid API key format. Must start with sk_live_ or sk_test_");
54
+ }
55
+ this.pages = new PagesAPI(this);
56
+ this.documents = new DocumentsAPI(this);
57
+ this.youtube = new YouTubeAPI(this);
58
+ this.chat = new ChatAPI(this);
59
+ this.analyze = new AnalyzeAPI(this);
60
+ }
61
+ async request(endpoint, options = {}) {
62
+ const url = `${this.baseUrl}${endpoint}`;
63
+ const headers = {
64
+ "x-api-key": this.apiKey,
65
+ ...options.headers
66
+ };
67
+ if (options.body && typeof options.body === "string") {
68
+ headers["Content-Type"] = "application/json";
69
+ }
70
+ const controller = new AbortController();
71
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
72
+ try {
73
+ const response = await fetch(url, {
74
+ ...options,
75
+ headers,
76
+ signal: controller.signal
77
+ });
78
+ clearTimeout(timeoutId);
79
+ if (!response.ok) {
80
+ const errorData = await response.json().catch(() => ({}));
81
+ const message = errorData.error?.message || `Request failed with status ${response.status}`;
82
+ throw new SybilError(message, response.status, errorData.error?.code);
83
+ }
84
+ return response.json();
85
+ } catch (error) {
86
+ clearTimeout(timeoutId);
87
+ if (error instanceof SybilError) {
88
+ throw error;
89
+ }
90
+ if (error instanceof Error && error.name === "AbortError") {
91
+ throw new SybilError("Request timeout", 408, "TIMEOUT");
92
+ }
93
+ throw new SybilError(
94
+ error instanceof Error ? error.message : "Unknown error",
95
+ 500,
96
+ "UNKNOWN"
97
+ );
98
+ }
99
+ }
100
+ };
101
+ var SybilError = class extends Error {
102
+ constructor(message, status, code) {
103
+ super(message);
104
+ this.name = "SybilError";
105
+ this.status = status;
106
+ this.code = code;
107
+ }
108
+ };
109
+ var PagesAPI = class {
110
+ constructor(client) {
111
+ this.client = client;
112
+ }
113
+ async list(params = {}) {
114
+ const searchParams = new URLSearchParams();
115
+ if (params.limit) searchParams.set("limit", params.limit.toString());
116
+ if (params.offset) searchParams.set("offset", params.offset.toString());
117
+ if (params.parent_id) searchParams.set("parent_id", params.parent_id);
118
+ if (params.is_published !== void 0) searchParams.set("is_published", params.is_published.toString());
119
+ const query = searchParams.toString();
120
+ return this.client.request(`/pages${query ? `?${query}` : ""}`);
121
+ }
122
+ async get(pageId) {
123
+ return this.client.request(`/pages/${pageId}`);
124
+ }
125
+ async create(params = {}) {
126
+ return this.client.request("/pages", {
127
+ method: "POST",
128
+ body: JSON.stringify(params)
129
+ });
130
+ }
131
+ async update(pageId, params) {
132
+ return this.client.request(`/pages/${pageId}`, {
133
+ method: "PUT",
134
+ body: JSON.stringify(params)
135
+ });
136
+ }
137
+ async delete(pageId) {
138
+ return this.client.request(`/pages/${pageId}`, {
139
+ method: "DELETE"
140
+ });
141
+ }
142
+ async upload(file, fileName) {
143
+ const formData = new FormData();
144
+ formData.append("file", file, fileName);
145
+ return this.client.request("/pages/upload", {
146
+ method: "POST",
147
+ body: formData
148
+ });
149
+ }
150
+ async deleteFile(filePath) {
151
+ return this.client.request("/pages/upload", {
152
+ method: "DELETE",
153
+ body: JSON.stringify({ filePath })
154
+ });
155
+ }
156
+ };
157
+ var DocumentsAPI = class {
158
+ constructor(client) {
159
+ this.client = client;
160
+ }
161
+ async list(params = {}) {
162
+ const searchParams = new URLSearchParams();
163
+ if (params.limit) searchParams.set("limit", params.limit.toString());
164
+ if (params.offset) searchParams.set("offset", params.offset.toString());
165
+ if (params.status) searchParams.set("status", params.status);
166
+ if (params.fileType) searchParams.set("fileType", params.fileType);
167
+ if (params.search) searchParams.set("search", params.search);
168
+ const query = searchParams.toString();
169
+ return this.client.request(`/documents${query ? `?${query}` : ""}`);
170
+ }
171
+ async get(documentId, params = {}) {
172
+ const searchParams = new URLSearchParams();
173
+ if (params.includeContent) searchParams.set("includeContent", "true");
174
+ if (params.includeInsights === false) searchParams.set("includeInsights", "false");
175
+ if (params.includeMetadata === false) searchParams.set("includeMetadata", "false");
176
+ const query = searchParams.toString();
177
+ return this.client.request(`/documents/${documentId}${query ? `?${query}` : ""}`);
178
+ }
179
+ async process(file, options = {}) {
180
+ const formData = new FormData();
181
+ formData.append("file", file, options.fileName);
182
+ if (options.metadata) {
183
+ formData.append("metadata", JSON.stringify(options.metadata));
184
+ }
185
+ if (options.collectionId) {
186
+ formData.append("collectionId", options.collectionId);
187
+ }
188
+ return this.client.request("/documents", {
189
+ method: "POST",
190
+ body: formData
191
+ });
192
+ }
193
+ async status(documentId) {
194
+ return this.client.request(`/documents/${documentId}/status`);
195
+ }
196
+ async insights(documentId, type) {
197
+ const query = type ? `?type=${type}` : "";
198
+ return this.client.request(`/documents/${documentId}/insights${query}`);
199
+ }
200
+ async delete(documentId) {
201
+ return this.client.request(`/documents/${documentId}`, {
202
+ method: "DELETE"
203
+ });
204
+ }
205
+ async waitForProcessing(documentId, options = {}) {
206
+ const maxAttempts = options.maxAttempts || 60;
207
+ const interval = options.interval || 3e3;
208
+ for (let i = 0; i < maxAttempts; i++) {
209
+ const status = await this.status(documentId);
210
+ if (status.status === "processed" || status.status === "completed") {
211
+ const { document: document2 } = await this.get(documentId);
212
+ return document2;
213
+ }
214
+ if (status.status === "failed") {
215
+ throw new SybilError(status.error?.message || "Processing failed", 500, "PROCESSING_FAILED");
216
+ }
217
+ await new Promise((resolve) => setTimeout(resolve, interval));
218
+ }
219
+ throw new SybilError("Processing timeout", 408, "TIMEOUT");
220
+ }
221
+ };
222
+ var YouTubeAPI = class {
223
+ constructor(client) {
224
+ this.client = client;
225
+ }
226
+ async list(params = {}) {
227
+ const searchParams = new URLSearchParams();
228
+ if (params.limit) searchParams.set("limit", params.limit.toString());
229
+ if (params.offset) searchParams.set("offset", params.offset.toString());
230
+ const query = searchParams.toString();
231
+ return this.client.request(`/youtube${query ? `?${query}` : ""}`);
232
+ }
233
+ async process(url, options) {
234
+ return this.client.request("/youtube", {
235
+ method: "POST",
236
+ body: JSON.stringify({
237
+ url,
238
+ collectionId: options?.collectionId,
239
+ force: options?.force
240
+ })
241
+ });
242
+ }
243
+ async get(videoId, params = {}) {
244
+ const searchParams = new URLSearchParams();
245
+ if (params.includeTranscript) searchParams.set("includeTranscript", "true");
246
+ if (params.includeChunks) searchParams.set("includeChunks", "true");
247
+ if (params.includeInsights === false) searchParams.set("includeInsights", "false");
248
+ const query = searchParams.toString();
249
+ return this.client.request(`/youtube/${videoId}${query ? `?${query}` : ""}`);
250
+ }
251
+ async delete(videoId) {
252
+ return this.client.request(`/youtube/${videoId}`, {
253
+ method: "DELETE"
254
+ });
255
+ }
256
+ };
257
+ var ChatAPI = class {
258
+ constructor(client) {
259
+ this.client = client;
260
+ }
261
+ async send(paramsOrDocId, query) {
262
+ const params = typeof paramsOrDocId === "string" ? { documentId: paramsOrDocId, query } : paramsOrDocId;
263
+ return this.client.request("/chat", {
264
+ method: "POST",
265
+ body: JSON.stringify(params)
266
+ });
267
+ }
268
+ async history(documentId, limit) {
269
+ const searchParams = new URLSearchParams();
270
+ searchParams.set("documentId", documentId);
271
+ if (limit) searchParams.set("limit", limit.toString());
272
+ return this.client.request(`/chat?${searchParams.toString()}`);
273
+ }
274
+ };
275
+ var AnalyzeAPI = class {
276
+ constructor(client) {
277
+ this.client = client;
278
+ }
279
+ async run(paramsOrDocId, forceRefresh) {
280
+ const params = typeof paramsOrDocId === "string" ? { documentId: paramsOrDocId, forceRefresh } : paramsOrDocId;
281
+ return this.client.request("/analyze", {
282
+ method: "POST",
283
+ body: JSON.stringify(params)
284
+ });
285
+ }
286
+ async get(documentId) {
287
+ return this.client.request(`/analyze?documentId=${documentId}`);
288
+ }
289
+ };
290
+ function embedPage(options) {
291
+ const {
292
+ pageId,
293
+ apiKey,
294
+ container,
295
+ baseUrl = "https://app.sybil.studio",
296
+ theme = "dark",
297
+ readOnly = false,
298
+ toolbar = true,
299
+ minHeight = "400px",
300
+ maxHeight,
301
+ onReady,
302
+ onChange,
303
+ onSave,
304
+ onError
305
+ } = options;
306
+ const containerEl = typeof container === "string" ? document.querySelector(container) : container;
307
+ if (!containerEl) {
308
+ throw new Error("Container element not found");
309
+ }
310
+ const params = new URLSearchParams({
311
+ apiKey,
312
+ readOnly: readOnly.toString(),
313
+ toolbar: toolbar.toString(),
314
+ minHeight
315
+ });
316
+ if (typeof theme === "string") {
317
+ params.set("theme", theme);
318
+ } else {
319
+ if (theme.background) params.set("bg", theme.background);
320
+ if (theme.backgroundSecondary) params.set("bgSecondary", theme.backgroundSecondary);
321
+ if (theme.text) params.set("textColor", theme.text);
322
+ if (theme.textSecondary) params.set("textSecondary", theme.textSecondary);
323
+ if (theme.border) params.set("borderColor", theme.border);
324
+ if (theme.accent) params.set("accent", theme.accent);
325
+ }
326
+ const iframe = document.createElement("iframe");
327
+ iframe.src = `${baseUrl}/embed/pages/${pageId}?${params.toString()}`;
328
+ iframe.style.width = "100%";
329
+ iframe.style.minHeight = minHeight;
330
+ if (maxHeight) iframe.style.maxHeight = maxHeight;
331
+ iframe.style.border = "none";
332
+ iframe.style.borderRadius = "8px";
333
+ iframe.allow = "clipboard-write";
334
+ const handleMessage = (event) => {
335
+ if (event.origin !== new URL(baseUrl).origin) return;
336
+ switch (event.data?.type) {
337
+ case "sybil:page:ready":
338
+ onReady?.();
339
+ break;
340
+ case "sybil:page:changed":
341
+ onChange?.(event.data.blocks);
342
+ break;
343
+ case "sybil:page:saved":
344
+ onSave?.();
345
+ break;
346
+ case "sybil:page:error":
347
+ onError?.(new Error(event.data.error));
348
+ break;
349
+ case "sybil:content":
350
+ break;
351
+ }
352
+ };
353
+ window.addEventListener("message", handleMessage);
354
+ containerEl.appendChild(iframe);
355
+ return {
356
+ getContent: () => {
357
+ return new Promise((resolve) => {
358
+ const handler = (event) => {
359
+ if (event.data?.type === "sybil:content") {
360
+ window.removeEventListener("message", handler);
361
+ resolve(event.data.blocks);
362
+ }
363
+ };
364
+ window.addEventListener("message", handler);
365
+ iframe.contentWindow?.postMessage({ type: "sybil:getContent" }, baseUrl);
366
+ });
367
+ },
368
+ setContent: (blocks) => {
369
+ iframe.contentWindow?.postMessage({ type: "sybil:setContent", blocks }, baseUrl);
370
+ },
371
+ destroy: () => {
372
+ window.removeEventListener("message", handleMessage);
373
+ iframe.remove();
374
+ }
375
+ };
376
+ }
377
+
378
+ // src/react/SybilPages.tsx
379
+ var import_jsx_runtime = require("react/jsx-runtime");
380
+ var SybilPages = (0, import_react.forwardRef)(function SybilPages2({
381
+ apiKey,
382
+ pageId,
383
+ baseUrl,
384
+ theme = "dark",
385
+ readOnly = false,
386
+ toolbar = true,
387
+ minHeight = "400px",
388
+ maxHeight,
389
+ className,
390
+ style,
391
+ onReady,
392
+ onChange,
393
+ onSave,
394
+ onError
395
+ }, ref) {
396
+ const containerRef = (0, import_react.useRef)(null);
397
+ const instanceRef = (0, import_react.useRef)(null);
398
+ (0, import_react.useImperativeHandle)(ref, () => ({
399
+ getContent: async () => {
400
+ if (!instanceRef.current) return [];
401
+ return instanceRef.current.getContent();
402
+ },
403
+ setContent: (blocks) => {
404
+ instanceRef.current?.setContent(blocks);
405
+ }
406
+ }));
407
+ (0, import_react.useEffect)(() => {
408
+ if (!containerRef.current || !pageId || !apiKey) return;
409
+ instanceRef.current?.destroy();
410
+ instanceRef.current = embedPage({
411
+ pageId,
412
+ apiKey,
413
+ container: containerRef.current,
414
+ baseUrl,
415
+ theme,
416
+ readOnly,
417
+ toolbar,
418
+ minHeight,
419
+ maxHeight,
420
+ onReady,
421
+ onChange,
422
+ onSave,
423
+ onError
424
+ });
425
+ return () => {
426
+ instanceRef.current?.destroy();
427
+ instanceRef.current = null;
428
+ };
429
+ }, [pageId, apiKey, baseUrl, theme, readOnly, toolbar, minHeight, maxHeight]);
430
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
431
+ "div",
432
+ {
433
+ ref: containerRef,
434
+ className,
435
+ style: {
436
+ minHeight,
437
+ maxHeight,
438
+ ...style
439
+ }
440
+ }
441
+ );
442
+ });
443
+
444
+ // src/react/SybilAtlas.tsx
445
+ var import_react2 = require("react");
446
+
447
+ // src/atlas/client.ts
448
+ var DEFAULT_BASE_URL2 = "https://app.sybil.studio";
449
+ var AtlasLogger = class {
450
+ constructor(config) {
451
+ this.logs = [];
452
+ this.config = config;
453
+ }
454
+ log(level, category, message, data, duration) {
455
+ if (!this.config?.enabled) return;
456
+ const levels = ["debug", "info", "warn", "error"];
457
+ const configLevel = this.config.level || "info";
458
+ if (levels.indexOf(level) < levels.indexOf(configLevel)) return;
459
+ const entry = {
460
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
461
+ level,
462
+ category,
463
+ message,
464
+ data,
465
+ duration
466
+ };
467
+ this.logs.push(entry);
468
+ this.config.onLog?.(entry);
469
+ if (typeof console !== "undefined") {
470
+ const prefix = `[Atlas SDK] [${category}]`;
471
+ switch (level) {
472
+ case "debug":
473
+ console.debug(prefix, message, data || "");
474
+ break;
475
+ case "info":
476
+ console.info(prefix, message, data || "");
477
+ break;
478
+ case "warn":
479
+ console.warn(prefix, message, data || "");
480
+ break;
481
+ case "error":
482
+ console.error(prefix, message, data || "");
483
+ break;
484
+ }
485
+ }
486
+ }
487
+ getLogs() {
488
+ return [...this.logs];
489
+ }
490
+ clearLogs() {
491
+ this.logs = [];
492
+ }
493
+ };
494
+ function embedAtlas(config) {
495
+ const {
496
+ apiKey,
497
+ workspaceId,
498
+ container,
499
+ baseUrl = DEFAULT_BASE_URL2,
500
+ theme = "dark",
501
+ showSidebar = true,
502
+ sidebarWidth = 260,
503
+ sidebarCollapsible = true,
504
+ readOnly = false,
505
+ defaultPageId,
506
+ allowCreate = true,
507
+ allowDelete = true,
508
+ allowExport = true,
509
+ features = {},
510
+ logging,
511
+ onReady,
512
+ onPageChange,
513
+ onPageCreate,
514
+ onPageDelete,
515
+ onPageUpdate,
516
+ onError,
517
+ onNavigate
518
+ } = config;
519
+ const logger = new AtlasLogger(logging);
520
+ const startTime = Date.now();
521
+ logger.log("info", "render", "Initializing Atlas embed", {
522
+ workspaceId,
523
+ showSidebar,
524
+ readOnly,
525
+ features
526
+ });
527
+ const containerEl = typeof container === "string" ? document.querySelector(container) : container;
528
+ if (!containerEl) {
529
+ const error = {
530
+ code: "CONTAINER_NOT_FOUND",
531
+ message: "Container element not found",
532
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
533
+ };
534
+ onError?.(error);
535
+ throw new Error(error.message);
536
+ }
537
+ const params = new URLSearchParams({
538
+ apiKey,
539
+ workspaceId,
540
+ readOnly: readOnly.toString(),
541
+ showSidebar: showSidebar.toString(),
542
+ sidebarWidth: sidebarWidth.toString(),
543
+ sidebarCollapsible: sidebarCollapsible.toString(),
544
+ allowCreate: allowCreate.toString(),
545
+ allowDelete: allowDelete.toString(),
546
+ allowExport: allowExport.toString()
547
+ });
548
+ if (defaultPageId) params.set("defaultPageId", defaultPageId);
549
+ if (typeof theme === "string") {
550
+ params.set("theme", theme);
551
+ } else {
552
+ Object.entries(theme).forEach(([key, value]) => {
553
+ if (value) params.set(`theme_${key}`, value);
554
+ });
555
+ }
556
+ Object.entries(features).forEach(([key, value]) => {
557
+ if (typeof value === "boolean") {
558
+ params.set(`feature_${key}`, value.toString());
559
+ }
560
+ });
561
+ const iframe = document.createElement("iframe");
562
+ iframe.src = `${baseUrl}/embed/atlas?${params.toString()}`;
563
+ iframe.style.width = "100%";
564
+ iframe.style.height = "100%";
565
+ iframe.style.border = "none";
566
+ iframe.style.borderRadius = "8px";
567
+ iframe.allow = "clipboard-write";
568
+ let currentPage = null;
569
+ let isReady = false;
570
+ const createError = (code, message, status) => ({
571
+ code,
572
+ message,
573
+ status,
574
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
575
+ requestId: `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
576
+ });
577
+ const apiRequest = async (endpoint, options = {}) => {
578
+ const requestStart = Date.now();
579
+ const url = `${baseUrl}/api/sdk/v1${endpoint}`;
580
+ logger.log("debug", "api", `Request: ${options.method || "GET"} ${endpoint}`, {
581
+ url,
582
+ method: options.method || "GET"
583
+ });
584
+ try {
585
+ const response = await fetch(url, {
586
+ ...options,
587
+ headers: {
588
+ "x-api-key": apiKey,
589
+ "Content-Type": "application/json",
590
+ ...options.headers
591
+ }
592
+ });
593
+ const duration = Date.now() - requestStart;
594
+ if (!response.ok) {
595
+ const errorData = await response.json().catch(() => ({}));
596
+ const error = createError(
597
+ errorData.error?.code || "API_ERROR",
598
+ errorData.error?.message || `Request failed with status ${response.status}`,
599
+ response.status
600
+ );
601
+ logger.log("error", "api", `Request failed: ${endpoint}`, {
602
+ status: response.status,
603
+ error: errorData
604
+ }, duration);
605
+ onError?.(error);
606
+ throw error;
607
+ }
608
+ const data = await response.json();
609
+ logger.log("debug", "api", `Response: ${endpoint}`, { status: response.status }, duration);
610
+ return data;
611
+ } catch (err) {
612
+ if (err.code) throw err;
613
+ const error = createError("NETWORK_ERROR", err.message);
614
+ logger.log("error", "api", "Network error", { error: err.message });
615
+ onError?.(error);
616
+ throw error;
617
+ }
618
+ };
619
+ const postMessage = (type, payload) => {
620
+ iframe.contentWindow?.postMessage({ type, ...payload }, baseUrl);
621
+ };
622
+ const handleMessage = (event) => {
623
+ if (event.origin !== new URL(baseUrl).origin) return;
624
+ const { type, ...data } = event.data || {};
625
+ logger.log("debug", "render", `Message received: ${type}`, data);
626
+ switch (type) {
627
+ case "sybil:atlas:ready":
628
+ isReady = true;
629
+ logger.log("info", "render", "Atlas embed ready", {}, Date.now() - startTime);
630
+ onReady?.(instance);
631
+ break;
632
+ case "sybil:atlas:page:changed":
633
+ currentPage = data.page;
634
+ logger.log("info", "navigation", "Page changed", { pageId: data.page?.id });
635
+ onPageChange?.(data.page);
636
+ break;
637
+ case "sybil:atlas:page:created":
638
+ logger.log("info", "editor", "Page created", { pageId: data.page?.id });
639
+ onPageCreate?.(data.page);
640
+ break;
641
+ case "sybil:atlas:page:deleted":
642
+ logger.log("info", "editor", "Page deleted", { pageId: data.pageId });
643
+ onPageDelete?.(data.pageId);
644
+ break;
645
+ case "sybil:atlas:page:updated":
646
+ currentPage = data.page;
647
+ logger.log("debug", "sync", "Page updated", { pageId: data.page?.id });
648
+ onPageUpdate?.(data.page);
649
+ break;
650
+ case "sybil:atlas:navigate":
651
+ logger.log("info", "navigation", "Navigation requested", { pageId: data.pageId });
652
+ onNavigate?.(data.pageId);
653
+ break;
654
+ case "sybil:atlas:error":
655
+ const error = createError(data.code || "EMBED_ERROR", data.message);
656
+ logger.log("error", "render", "Embed error", data);
657
+ onError?.(error);
658
+ break;
659
+ }
660
+ };
661
+ window.addEventListener("message", handleMessage);
662
+ containerEl.appendChild(iframe);
663
+ const instance = {
664
+ getPages: async () => {
665
+ logger.log("info", "api", "Fetching pages");
666
+ const response = await apiRequest(
667
+ `/atlas/workspaces/${workspaceId}/sidebar`
668
+ );
669
+ return response.sidebar;
670
+ },
671
+ getPage: async (pageId) => {
672
+ logger.log("info", "api", "Fetching page", { pageId });
673
+ const response = await apiRequest(
674
+ `/atlas/pages/${pageId}`
675
+ );
676
+ return response.page;
677
+ },
678
+ createPage: async (params2) => {
679
+ logger.log("info", "api", "Creating page", params2);
680
+ const response = await apiRequest(
681
+ `/atlas/workspaces/${workspaceId}/pages`,
682
+ {
683
+ method: "POST",
684
+ body: JSON.stringify(params2)
685
+ }
686
+ );
687
+ postMessage("sybil:atlas:refresh");
688
+ return response.page;
689
+ },
690
+ updatePage: async (pageId, params2) => {
691
+ logger.log("info", "api", "Updating page", { pageId, ...params2 });
692
+ const response = await apiRequest(
693
+ `/atlas/pages/${pageId}`,
694
+ {
695
+ method: "PUT",
696
+ body: JSON.stringify(params2)
697
+ }
698
+ );
699
+ postMessage("sybil:atlas:refresh");
700
+ return response.page;
701
+ },
702
+ deletePage: async (pageId) => {
703
+ logger.log("info", "api", "Deleting page", { pageId });
704
+ await apiRequest(`/atlas/pages/${pageId}`, { method: "DELETE" });
705
+ postMessage("sybil:atlas:refresh");
706
+ },
707
+ navigateTo: (pageId) => {
708
+ logger.log("info", "navigation", "Navigating to page", { pageId });
709
+ postMessage("sybil:atlas:navigate", { pageId });
710
+ },
711
+ getCurrentPage: () => currentPage,
712
+ exportPage: async (pageId, format) => {
713
+ logger.log("info", "api", "Exporting page", { pageId, format });
714
+ const response = await fetch(
715
+ `${baseUrl}/api/sdk/v1/atlas/pages/${pageId}/export?format=${format}`,
716
+ {
717
+ headers: { "x-api-key": apiKey }
718
+ }
719
+ );
720
+ if (!response.ok) {
721
+ const error = createError("EXPORT_FAILED", "Failed to export page");
722
+ onError?.(error);
723
+ throw error;
724
+ }
725
+ return response.blob();
726
+ },
727
+ toggleSidebar: () => {
728
+ logger.log("debug", "render", "Toggling sidebar");
729
+ postMessage("sybil:atlas:toggleSidebar");
730
+ },
731
+ setSidebarWidth: (width) => {
732
+ logger.log("debug", "render", "Setting sidebar width", { width });
733
+ postMessage("sybil:atlas:setSidebarWidth", { width });
734
+ },
735
+ setTheme: (newTheme) => {
736
+ logger.log("debug", "render", "Setting theme", { theme: newTheme });
737
+ postMessage("sybil:atlas:setTheme", { theme: newTheme });
738
+ },
739
+ refresh: async () => {
740
+ logger.log("info", "sync", "Refreshing");
741
+ postMessage("sybil:atlas:refresh");
742
+ },
743
+ destroy: () => {
744
+ logger.log("info", "render", "Destroying Atlas embed");
745
+ window.removeEventListener("message", handleMessage);
746
+ iframe.remove();
747
+ },
748
+ getLogs: () => logger.getLogs(),
749
+ clearLogs: () => logger.clearLogs()
750
+ };
751
+ return instance;
752
+ }
753
+ var AtlasClient = class {
754
+ constructor(config) {
755
+ this.apiKey = config.apiKey;
756
+ this.workspaceId = config.workspaceId;
757
+ this.baseUrl = config.baseUrl || DEFAULT_BASE_URL2;
758
+ this.logger = new AtlasLogger(config.logging);
759
+ }
760
+ async request(endpoint, options = {}) {
761
+ const url = `${this.baseUrl}/api/sdk/v1${endpoint}`;
762
+ const startTime = Date.now();
763
+ this.logger.log("debug", "api", `Request: ${options.method || "GET"} ${endpoint}`);
764
+ const response = await fetch(url, {
765
+ ...options,
766
+ headers: {
767
+ "x-api-key": this.apiKey,
768
+ "Content-Type": "application/json",
769
+ ...options.headers
770
+ }
771
+ });
772
+ const duration = Date.now() - startTime;
773
+ if (!response.ok) {
774
+ const errorData = await response.json().catch(() => ({}));
775
+ this.logger.log("error", "api", `Request failed: ${endpoint}`, {
776
+ status: response.status,
777
+ error: errorData
778
+ }, duration);
779
+ throw new Error(errorData.error?.message || `Request failed with status ${response.status}`);
780
+ }
781
+ this.logger.log("debug", "api", `Response: ${endpoint}`, { status: response.status }, duration);
782
+ return response.json();
783
+ }
784
+ async getSidebar() {
785
+ const response = await this.request(
786
+ `/atlas/workspaces/${this.workspaceId}/sidebar`
787
+ );
788
+ return response.sidebar;
789
+ }
790
+ async getPage(pageId) {
791
+ const response = await this.request(`/atlas/pages/${pageId}`);
792
+ return response.page;
793
+ }
794
+ async createPage(params = {}) {
795
+ const response = await this.request(
796
+ `/atlas/workspaces/${this.workspaceId}/pages`,
797
+ { method: "POST", body: JSON.stringify(params) }
798
+ );
799
+ return response.page;
800
+ }
801
+ async updatePage(pageId, params) {
802
+ const response = await this.request(
803
+ `/atlas/pages/${pageId}`,
804
+ { method: "PUT", body: JSON.stringify(params) }
805
+ );
806
+ return response.page;
807
+ }
808
+ async deletePage(pageId) {
809
+ await this.request(`/atlas/pages/${pageId}`, { method: "DELETE" });
810
+ }
811
+ async exportPage(pageId, format) {
812
+ const response = await fetch(
813
+ `${this.baseUrl}/api/sdk/v1/atlas/pages/${pageId}/export?format=${format}`,
814
+ { headers: { "x-api-key": this.apiKey } }
815
+ );
816
+ if (!response.ok) throw new Error("Failed to export page");
817
+ return response.blob();
818
+ }
819
+ async toggleFavorite(pageId) {
820
+ const response = await this.request(
821
+ `/atlas/pages/${pageId}/favorite`,
822
+ { method: "POST" }
823
+ );
824
+ return response.page;
825
+ }
826
+ getLogs() {
827
+ return this.logger.getLogs();
828
+ }
829
+ clearLogs() {
830
+ this.logger.clearLogs();
831
+ }
832
+ };
833
+
834
+ // src/react/SybilAtlas.tsx
835
+ var import_jsx_runtime2 = require("react/jsx-runtime");
836
+ var SybilAtlas = (0, import_react2.forwardRef)(function SybilAtlas2({
837
+ apiKey,
838
+ workspaceId,
839
+ baseUrl,
840
+ theme = "dark",
841
+ showSidebar = true,
842
+ sidebarWidth = 260,
843
+ sidebarCollapsible = true,
844
+ readOnly = false,
845
+ defaultPageId,
846
+ allowCreate = true,
847
+ allowDelete = true,
848
+ allowExport = true,
849
+ features,
850
+ logging,
851
+ className,
852
+ style,
853
+ onReady,
854
+ onPageChange,
855
+ onPageCreate,
856
+ onPageDelete,
857
+ onPageUpdate,
858
+ onError,
859
+ onNavigate
860
+ }, ref) {
861
+ const containerRef = (0, import_react2.useRef)(null);
862
+ const instanceRef = (0, import_react2.useRef)(null);
863
+ (0, import_react2.useImperativeHandle)(ref, () => ({
864
+ getPages: async () => {
865
+ if (!instanceRef.current) throw new Error("Atlas not initialized");
866
+ return instanceRef.current.getPages();
867
+ },
868
+ getPage: async (pageId) => {
869
+ if (!instanceRef.current) throw new Error("Atlas not initialized");
870
+ return instanceRef.current.getPage(pageId);
871
+ },
872
+ createPage: async (params) => {
873
+ if (!instanceRef.current) throw new Error("Atlas not initialized");
874
+ return instanceRef.current.createPage(params || {});
875
+ },
876
+ updatePage: async (pageId, params) => {
877
+ if (!instanceRef.current) throw new Error("Atlas not initialized");
878
+ return instanceRef.current.updatePage(pageId, params);
879
+ },
880
+ deletePage: async (pageId) => {
881
+ if (!instanceRef.current) throw new Error("Atlas not initialized");
882
+ return instanceRef.current.deletePage(pageId);
883
+ },
884
+ navigateTo: (pageId) => {
885
+ instanceRef.current?.navigateTo(pageId);
886
+ },
887
+ getCurrentPage: () => {
888
+ return instanceRef.current?.getCurrentPage() || null;
889
+ },
890
+ exportPage: async (pageId, format) => {
891
+ if (!instanceRef.current) throw new Error("Atlas not initialized");
892
+ return instanceRef.current.exportPage(pageId, format);
893
+ },
894
+ toggleSidebar: () => {
895
+ instanceRef.current?.toggleSidebar();
896
+ },
897
+ setSidebarWidth: (width) => {
898
+ instanceRef.current?.setSidebarWidth(width);
899
+ },
900
+ setTheme: (newTheme) => {
901
+ instanceRef.current?.setTheme(newTheme);
902
+ },
903
+ refresh: async () => {
904
+ return instanceRef.current?.refresh();
905
+ },
906
+ getLogs: () => {
907
+ return instanceRef.current?.getLogs() || [];
908
+ },
909
+ clearLogs: () => {
910
+ instanceRef.current?.clearLogs();
911
+ }
912
+ }));
913
+ (0, import_react2.useEffect)(() => {
914
+ if (!containerRef.current || !apiKey || !workspaceId) return;
915
+ instanceRef.current?.destroy();
916
+ const config = {
917
+ apiKey,
918
+ workspaceId,
919
+ container: containerRef.current,
920
+ baseUrl,
921
+ theme,
922
+ showSidebar,
923
+ sidebarWidth,
924
+ sidebarCollapsible,
925
+ readOnly,
926
+ defaultPageId,
927
+ allowCreate,
928
+ allowDelete,
929
+ allowExport,
930
+ features,
931
+ logging,
932
+ onReady,
933
+ onPageChange,
934
+ onPageCreate,
935
+ onPageDelete,
936
+ onPageUpdate,
937
+ onError,
938
+ onNavigate
939
+ };
940
+ instanceRef.current = embedAtlas(config);
941
+ return () => {
942
+ instanceRef.current?.destroy();
943
+ instanceRef.current = null;
944
+ };
945
+ }, [apiKey, workspaceId, baseUrl]);
946
+ (0, import_react2.useEffect)(() => {
947
+ instanceRef.current?.setTheme(theme);
948
+ }, [theme]);
949
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
950
+ "div",
951
+ {
952
+ ref: containerRef,
953
+ className,
954
+ style: {
955
+ width: "100%",
956
+ height: "100%",
957
+ minHeight: "500px",
958
+ ...style
959
+ }
960
+ }
961
+ );
962
+ });
963
+
964
+ // src/react/SybilNexus.tsx
965
+ var import_react3 = require("react");
966
+
967
+ // src/nexus/client.ts
968
+ var DEFAULT_BASE_URL3 = "https://app.sybil.studio";
969
+ var NexusLogger = class {
970
+ constructor(config) {
971
+ this.logs = [];
972
+ this.config = config;
973
+ }
974
+ log(level, category, message, data, duration) {
975
+ if (!this.config?.enabled) return;
976
+ const levels = ["debug", "info", "warn", "error"];
977
+ const configLevel = this.config.level || "info";
978
+ if (levels.indexOf(level) < levels.indexOf(configLevel)) return;
979
+ const entry = {
980
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
981
+ level,
982
+ category,
983
+ message,
984
+ data,
985
+ duration,
986
+ fileId: data?.fileId,
987
+ folderId: data?.folderId
988
+ };
989
+ this.logs.push(entry);
990
+ this.config.onLog?.(entry);
991
+ if (typeof console !== "undefined") {
992
+ const prefix = `[Nexus SDK] [${category}]`;
993
+ switch (level) {
994
+ case "debug":
995
+ console.debug(prefix, message, data || "");
996
+ break;
997
+ case "info":
998
+ console.info(prefix, message, data || "");
999
+ break;
1000
+ case "warn":
1001
+ console.warn(prefix, message, data || "");
1002
+ break;
1003
+ case "error":
1004
+ console.error(prefix, message, data || "");
1005
+ break;
1006
+ }
1007
+ }
1008
+ }
1009
+ getLogs() {
1010
+ return [...this.logs];
1011
+ }
1012
+ clearLogs() {
1013
+ this.logs = [];
1014
+ }
1015
+ };
1016
+ function embedNexus(config) {
1017
+ const {
1018
+ apiKey,
1019
+ workspaceId,
1020
+ container,
1021
+ baseUrl = DEFAULT_BASE_URL3,
1022
+ theme = "dark",
1023
+ initialFolderId = null,
1024
+ viewMode = "list",
1025
+ showSidebar = true,
1026
+ showActivityFeed = true,
1027
+ showBreadcrumbs = true,
1028
+ showSearch = true,
1029
+ allowUpload = true,
1030
+ allowDownload = true,
1031
+ allowDelete = true,
1032
+ allowMove = true,
1033
+ allowRename = true,
1034
+ allowCreateFolder = true,
1035
+ allowMultiSelect = true,
1036
+ maxUploadSize,
1037
+ acceptedFileTypes,
1038
+ features = {},
1039
+ logging,
1040
+ onReady,
1041
+ onNavigate,
1042
+ onFileSelect,
1043
+ onFileOpen,
1044
+ onFileUpload,
1045
+ onFileDelete,
1046
+ onFolderCreate,
1047
+ onFolderDelete,
1048
+ onSelectionChange,
1049
+ onError
1050
+ } = config;
1051
+ const logger = new NexusLogger(logging);
1052
+ const startTime = Date.now();
1053
+ logger.log("info", "ui", "Initializing Nexus embed", {
1054
+ workspaceId,
1055
+ initialFolderId,
1056
+ viewMode,
1057
+ features
1058
+ });
1059
+ const containerEl = typeof container === "string" ? document.querySelector(container) : container;
1060
+ if (!containerEl) {
1061
+ const error = {
1062
+ code: "CONTAINER_NOT_FOUND",
1063
+ message: "Container element not found",
1064
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1065
+ };
1066
+ onError?.(error);
1067
+ throw new Error(error.message);
1068
+ }
1069
+ const params = new URLSearchParams({
1070
+ apiKey,
1071
+ workspaceId,
1072
+ viewMode,
1073
+ showSidebar: showSidebar.toString(),
1074
+ showActivityFeed: showActivityFeed.toString(),
1075
+ showBreadcrumbs: showBreadcrumbs.toString(),
1076
+ showSearch: showSearch.toString(),
1077
+ allowUpload: allowUpload.toString(),
1078
+ allowDownload: allowDownload.toString(),
1079
+ allowDelete: allowDelete.toString(),
1080
+ allowMove: allowMove.toString(),
1081
+ allowRename: allowRename.toString(),
1082
+ allowCreateFolder: allowCreateFolder.toString(),
1083
+ allowMultiSelect: allowMultiSelect.toString()
1084
+ });
1085
+ if (initialFolderId) params.set("folderId", initialFolderId);
1086
+ if (maxUploadSize) params.set("maxUploadSize", maxUploadSize.toString());
1087
+ if (acceptedFileTypes?.length) params.set("acceptedFileTypes", acceptedFileTypes.join(","));
1088
+ if (typeof theme === "string") {
1089
+ params.set("theme", theme);
1090
+ } else {
1091
+ Object.entries(theme).forEach(([key, value]) => {
1092
+ if (value) params.set(`theme_${key}`, value);
1093
+ });
1094
+ }
1095
+ Object.entries(features).forEach(([key, value]) => {
1096
+ if (typeof value === "boolean") {
1097
+ params.set(`feature_${key}`, value.toString());
1098
+ }
1099
+ });
1100
+ const iframe = document.createElement("iframe");
1101
+ iframe.src = `${baseUrl}/embed/nexus?${params.toString()}`;
1102
+ iframe.style.width = "100%";
1103
+ iframe.style.height = "100%";
1104
+ iframe.style.border = "none";
1105
+ iframe.style.borderRadius = "8px";
1106
+ iframe.allow = "clipboard-write";
1107
+ let currentFolderId = initialFolderId;
1108
+ let selectedItems = [];
1109
+ let isReady = false;
1110
+ const createError = (code, message, status) => ({
1111
+ code,
1112
+ message,
1113
+ status,
1114
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1115
+ requestId: `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
1116
+ });
1117
+ const apiRequest = async (endpoint, options = {}) => {
1118
+ const requestStart = Date.now();
1119
+ const url = `${baseUrl}/api/sdk/v1${endpoint}`;
1120
+ logger.log("debug", "api", `Request: ${options.method || "GET"} ${endpoint}`, {
1121
+ url,
1122
+ method: options.method || "GET"
1123
+ });
1124
+ try {
1125
+ const response = await fetch(url, {
1126
+ ...options,
1127
+ headers: {
1128
+ "x-api-key": apiKey,
1129
+ ...options.body instanceof FormData ? {} : { "Content-Type": "application/json" },
1130
+ ...options.headers
1131
+ }
1132
+ });
1133
+ const duration = Date.now() - requestStart;
1134
+ if (!response.ok) {
1135
+ const errorData = await response.json().catch(() => ({}));
1136
+ const error = createError(
1137
+ errorData.error?.code || "API_ERROR",
1138
+ errorData.error?.message || `Request failed with status ${response.status}`,
1139
+ response.status
1140
+ );
1141
+ logger.log("error", "api", `Request failed: ${endpoint}`, {
1142
+ status: response.status,
1143
+ error: errorData
1144
+ }, duration);
1145
+ onError?.(error);
1146
+ throw error;
1147
+ }
1148
+ const data = await response.json();
1149
+ logger.log("debug", "api", `Response: ${endpoint}`, { status: response.status }, duration);
1150
+ return data;
1151
+ } catch (err) {
1152
+ if (err.code) throw err;
1153
+ const error = createError("NETWORK_ERROR", err.message);
1154
+ logger.log("error", "api", "Network error", { error: err.message });
1155
+ onError?.(error);
1156
+ throw error;
1157
+ }
1158
+ };
1159
+ const postMessage = (type, payload) => {
1160
+ iframe.contentWindow?.postMessage({ type, ...payload }, baseUrl);
1161
+ };
1162
+ const handleMessage = (event) => {
1163
+ if (event.origin !== new URL(baseUrl).origin) return;
1164
+ const { type, ...data } = event.data || {};
1165
+ logger.log("debug", "ui", `Message received: ${type}`, data);
1166
+ switch (type) {
1167
+ case "sybil:nexus:ready":
1168
+ isReady = true;
1169
+ logger.log("info", "ui", "Nexus embed ready", {}, Date.now() - startTime);
1170
+ onReady?.(instance);
1171
+ break;
1172
+ case "sybil:nexus:navigate":
1173
+ currentFolderId = data.folderId;
1174
+ logger.log("info", "navigation", "Navigated to folder", { folderId: data.folderId });
1175
+ onNavigate?.(data.folderId);
1176
+ break;
1177
+ case "sybil:nexus:file:select":
1178
+ logger.log("debug", "selection", "File selected", { fileId: data.file?.id });
1179
+ onFileSelect?.(data.file);
1180
+ break;
1181
+ case "sybil:nexus:file:open":
1182
+ logger.log("info", "ui", "File opened", { fileId: data.file?.id });
1183
+ onFileOpen?.(data.file);
1184
+ break;
1185
+ case "sybil:nexus:file:upload":
1186
+ logger.log("info", "upload", "File uploaded", { fileId: data.file?.id });
1187
+ onFileUpload?.(data.file);
1188
+ break;
1189
+ case "sybil:nexus:file:delete":
1190
+ logger.log("info", "api", "File deleted", { fileId: data.fileId });
1191
+ onFileDelete?.(data.fileId);
1192
+ break;
1193
+ case "sybil:nexus:folder:create":
1194
+ logger.log("info", "api", "Folder created", { folderId: data.folder?.id });
1195
+ onFolderCreate?.(data.folder);
1196
+ break;
1197
+ case "sybil:nexus:folder:delete":
1198
+ logger.log("info", "api", "Folder deleted", { folderId: data.folderId });
1199
+ onFolderDelete?.(data.folderId);
1200
+ break;
1201
+ case "sybil:nexus:selection:change":
1202
+ selectedItems = data.items || [];
1203
+ logger.log("debug", "selection", "Selection changed", { count: selectedItems.length });
1204
+ onSelectionChange?.(selectedItems);
1205
+ break;
1206
+ case "sybil:nexus:error":
1207
+ const error = createError(data.code || "EMBED_ERROR", data.message);
1208
+ logger.log("error", "ui", "Embed error", data);
1209
+ onError?.(error);
1210
+ break;
1211
+ }
1212
+ };
1213
+ window.addEventListener("message", handleMessage);
1214
+ containerEl.appendChild(iframe);
1215
+ const instance = {
1216
+ getFiles: async (folderId) => {
1217
+ logger.log("info", "api", "Fetching files", { folderId });
1218
+ const params2 = new URLSearchParams({ workspaceId });
1219
+ if (folderId !== void 0) params2.set("folderId", folderId || "null");
1220
+ const response = await apiRequest(
1221
+ `/nexus/files?${params2.toString()}`
1222
+ );
1223
+ return response.files.map((f) => ({
1224
+ ...f,
1225
+ itemType: "file"
1226
+ }));
1227
+ },
1228
+ getFolders: async (parentId) => {
1229
+ logger.log("info", "api", "Fetching folders", { parentId });
1230
+ const params2 = new URLSearchParams({ workspaceId });
1231
+ if (parentId !== void 0) params2.set("parentId", parentId || "null");
1232
+ const response = await apiRequest(
1233
+ `/nexus/folders?${params2.toString()}`
1234
+ );
1235
+ return response.folders;
1236
+ },
1237
+ getFolderContents: async (folderId) => {
1238
+ logger.log("info", "api", "Fetching folder contents", { folderId });
1239
+ const params2 = new URLSearchParams({ workspaceId });
1240
+ if (folderId) params2.set("folderId", folderId);
1241
+ const response = await apiRequest(
1242
+ `/nexus/folders/contents?${params2.toString()}`
1243
+ );
1244
+ return response;
1245
+ },
1246
+ getFolderTree: async () => {
1247
+ logger.log("info", "api", "Fetching folder tree");
1248
+ const response = await apiRequest(
1249
+ `/nexus/folders/tree?workspaceId=${workspaceId}`
1250
+ );
1251
+ return response.tree;
1252
+ },
1253
+ getFile: async (fileId) => {
1254
+ logger.log("info", "api", "Fetching file", { fileId });
1255
+ const response = await apiRequest(`/nexus/files/${fileId}`);
1256
+ return response.file;
1257
+ },
1258
+ getFolder: async (folderId) => {
1259
+ logger.log("info", "api", "Fetching folder", { folderId });
1260
+ const response = await apiRequest(
1261
+ `/nexus/folders/${folderId}`
1262
+ );
1263
+ return response.folder;
1264
+ },
1265
+ uploadFile: async (file, folderId, onProgress) => {
1266
+ logger.log("info", "upload", "Uploading file", { fileName: file.name, size: file.size, folderId });
1267
+ const formData = new FormData();
1268
+ formData.append("file", file);
1269
+ formData.append("workspaceId", workspaceId);
1270
+ if (folderId) formData.append("folderId", folderId);
1271
+ const xhr = new XMLHttpRequest();
1272
+ return new Promise((resolve, reject) => {
1273
+ xhr.upload.addEventListener("progress", (e) => {
1274
+ if (e.lengthComputable) {
1275
+ const progress = Math.round(e.loaded / e.total * 100);
1276
+ logger.log("debug", "upload", "Upload progress", { progress, fileName: file.name });
1277
+ onProgress?.(progress);
1278
+ }
1279
+ });
1280
+ xhr.addEventListener("load", () => {
1281
+ if (xhr.status >= 200 && xhr.status < 300) {
1282
+ const response = JSON.parse(xhr.responseText);
1283
+ logger.log("info", "upload", "Upload complete", { fileId: response.file?.id });
1284
+ postMessage("sybil:nexus:refresh");
1285
+ resolve(response.file);
1286
+ } else {
1287
+ const error = createError("UPLOAD_FAILED", "Failed to upload file", xhr.status);
1288
+ logger.log("error", "upload", "Upload failed", { status: xhr.status });
1289
+ onError?.(error);
1290
+ reject(error);
1291
+ }
1292
+ });
1293
+ xhr.addEventListener("error", () => {
1294
+ const error = createError("UPLOAD_ERROR", "Network error during upload");
1295
+ logger.log("error", "upload", "Upload network error");
1296
+ onError?.(error);
1297
+ reject(error);
1298
+ });
1299
+ xhr.open("POST", `${baseUrl}/api/sdk/v1/nexus/upload`);
1300
+ xhr.setRequestHeader("x-api-key", apiKey);
1301
+ xhr.send(formData);
1302
+ });
1303
+ },
1304
+ uploadFiles: async (files, folderId, onProgress) => {
1305
+ logger.log("info", "upload", "Uploading multiple files", { count: files.length, folderId });
1306
+ const results = [];
1307
+ for (let i = 0; i < files.length; i++) {
1308
+ const file = await instance.uploadFile(files[i], folderId, (progress) => {
1309
+ onProgress?.(i, progress);
1310
+ });
1311
+ results.push(file);
1312
+ }
1313
+ return results;
1314
+ },
1315
+ downloadFile: async (fileId) => {
1316
+ logger.log("info", "download", "Downloading file", { fileId });
1317
+ const response = await fetch(`${baseUrl}/api/sdk/v1/nexus/files/${fileId}/content`, {
1318
+ headers: { "x-api-key": apiKey }
1319
+ });
1320
+ if (!response.ok) {
1321
+ const error = createError("DOWNLOAD_FAILED", "Failed to download file", response.status);
1322
+ onError?.(error);
1323
+ throw error;
1324
+ }
1325
+ return response.blob();
1326
+ },
1327
+ getDownloadUrl: async (fileId) => {
1328
+ logger.log("info", "download", "Getting download URL", { fileId });
1329
+ const response = await apiRequest(`/nexus/files/${fileId}/url`);
1330
+ return response.signedUrl;
1331
+ },
1332
+ deleteFile: async (fileId) => {
1333
+ logger.log("info", "api", "Deleting file", { fileId });
1334
+ await apiRequest(`/nexus/files/${fileId}`, { method: "DELETE" });
1335
+ postMessage("sybil:nexus:refresh");
1336
+ },
1337
+ deleteFiles: async (fileIds) => {
1338
+ logger.log("info", "api", "Deleting multiple files", { count: fileIds.length });
1339
+ await apiRequest("/nexus/files/bulk", {
1340
+ method: "DELETE",
1341
+ body: JSON.stringify({ fileIds })
1342
+ });
1343
+ postMessage("sybil:nexus:refresh");
1344
+ },
1345
+ moveFile: async (fileId, targetFolderId) => {
1346
+ logger.log("info", "api", "Moving file", { fileId, targetFolderId });
1347
+ const response = await apiRequest(`/nexus/files/${fileId}`, {
1348
+ method: "PATCH",
1349
+ body: JSON.stringify({ folderId: targetFolderId })
1350
+ });
1351
+ postMessage("sybil:nexus:refresh");
1352
+ return response.file;
1353
+ },
1354
+ moveFiles: async (fileIds, targetFolderId) => {
1355
+ logger.log("info", "api", "Moving multiple files", { count: fileIds.length, targetFolderId });
1356
+ const response = await apiRequest("/nexus/files/bulk", {
1357
+ method: "PATCH",
1358
+ body: JSON.stringify({ fileIds, folderId: targetFolderId })
1359
+ });
1360
+ postMessage("sybil:nexus:refresh");
1361
+ return response.files;
1362
+ },
1363
+ renameFile: async (fileId, newName) => {
1364
+ logger.log("info", "api", "Renaming file", { fileId, newName });
1365
+ const response = await apiRequest(`/nexus/files/${fileId}`, {
1366
+ method: "PATCH",
1367
+ body: JSON.stringify({ name: newName })
1368
+ });
1369
+ postMessage("sybil:nexus:refresh");
1370
+ return response.file;
1371
+ },
1372
+ starFile: async (fileId, starred) => {
1373
+ logger.log("info", "api", "Starring file", { fileId, starred });
1374
+ const response = await apiRequest(`/nexus/files/${fileId}`, {
1375
+ method: "PATCH",
1376
+ body: JSON.stringify({ isStarred: starred })
1377
+ });
1378
+ postMessage("sybil:nexus:refresh");
1379
+ return response.file;
1380
+ },
1381
+ starFiles: async (fileIds, starred) => {
1382
+ logger.log("info", "api", "Starring multiple files", { count: fileIds.length, starred });
1383
+ await apiRequest("/nexus/files/bulk", {
1384
+ method: "PATCH",
1385
+ body: JSON.stringify({ fileIds, isStarred: starred })
1386
+ });
1387
+ postMessage("sybil:nexus:refresh");
1388
+ },
1389
+ trashFile: async (fileId) => {
1390
+ logger.log("info", "api", "Trashing file", { fileId });
1391
+ await apiRequest(`/nexus/files/${fileId}`, { method: "DELETE" });
1392
+ postMessage("sybil:nexus:refresh");
1393
+ },
1394
+ restoreFile: async (fileId, folderId) => {
1395
+ logger.log("info", "api", "Restoring file", { fileId, folderId });
1396
+ const response = await apiRequest(`/nexus/files/${fileId}/restore`, {
1397
+ method: "POST",
1398
+ body: JSON.stringify({ folderId })
1399
+ });
1400
+ postMessage("sybil:nexus:refresh");
1401
+ return response.file;
1402
+ },
1403
+ createFolder: async (name, parentId, options) => {
1404
+ logger.log("info", "api", "Creating folder", { name, parentId, options });
1405
+ const response = await apiRequest("/nexus/folders", {
1406
+ method: "POST",
1407
+ body: JSON.stringify({ workspaceId, name, parentId, ...options })
1408
+ });
1409
+ postMessage("sybil:nexus:refresh");
1410
+ return response.folder;
1411
+ },
1412
+ deleteFolder: async (folderId) => {
1413
+ logger.log("info", "api", "Deleting folder", { folderId });
1414
+ await apiRequest(`/nexus/folders/${folderId}`, { method: "DELETE" });
1415
+ postMessage("sybil:nexus:refresh");
1416
+ },
1417
+ moveFolder: async (folderId, targetParentId) => {
1418
+ logger.log("info", "api", "Moving folder", { folderId, targetParentId });
1419
+ const response = await apiRequest(`/nexus/folders/${folderId}`, {
1420
+ method: "PATCH",
1421
+ body: JSON.stringify({ parentId: targetParentId })
1422
+ });
1423
+ postMessage("sybil:nexus:refresh");
1424
+ return response.folder;
1425
+ },
1426
+ renameFolder: async (folderId, newName) => {
1427
+ logger.log("info", "api", "Renaming folder", { folderId, newName });
1428
+ const response = await apiRequest(`/nexus/folders/${folderId}`, {
1429
+ method: "PATCH",
1430
+ body: JSON.stringify({ name: newName })
1431
+ });
1432
+ postMessage("sybil:nexus:refresh");
1433
+ return response.folder;
1434
+ },
1435
+ navigateTo: (folderId) => {
1436
+ currentFolderId = folderId;
1437
+ logger.log("info", "navigation", "Navigating to folder", { folderId });
1438
+ postMessage("sybil:nexus:navigate", { folderId });
1439
+ },
1440
+ getCurrentFolder: () => currentFolderId,
1441
+ getSelection: () => [...selectedItems],
1442
+ setSelection: (itemIds) => {
1443
+ logger.log("debug", "selection", "Setting selection", { count: itemIds.length });
1444
+ postMessage("sybil:nexus:setSelection", { itemIds });
1445
+ },
1446
+ clearSelection: () => {
1447
+ logger.log("debug", "selection", "Clearing selection");
1448
+ postMessage("sybil:nexus:clearSelection");
1449
+ },
1450
+ selectAll: () => {
1451
+ logger.log("debug", "selection", "Selecting all");
1452
+ postMessage("sybil:nexus:selectAll");
1453
+ },
1454
+ setViewMode: (mode) => {
1455
+ logger.log("debug", "ui", "Setting view mode", { mode });
1456
+ postMessage("sybil:nexus:setViewMode", { mode });
1457
+ },
1458
+ toggleActivityFeed: () => {
1459
+ logger.log("debug", "ui", "Toggling activity feed");
1460
+ postMessage("sybil:nexus:toggleActivity");
1461
+ },
1462
+ toggleSidebar: () => {
1463
+ logger.log("debug", "ui", "Toggling sidebar");
1464
+ postMessage("sybil:nexus:toggleSidebar");
1465
+ },
1466
+ refresh: async () => {
1467
+ logger.log("info", "ui", "Refreshing");
1468
+ postMessage("sybil:nexus:refresh");
1469
+ },
1470
+ search: async (query) => {
1471
+ logger.log("info", "api", "Searching", { query });
1472
+ const params2 = new URLSearchParams({ workspaceId, search: query });
1473
+ const response = await apiRequest(
1474
+ `/nexus/files?${params2.toString()}`
1475
+ );
1476
+ return response.files.map((f) => ({
1477
+ ...f,
1478
+ itemType: "file"
1479
+ }));
1480
+ },
1481
+ getStats: async () => {
1482
+ logger.log("info", "api", "Fetching stats");
1483
+ const response = await apiRequest(
1484
+ `/nexus/stats?workspaceId=${workspaceId}`
1485
+ );
1486
+ return response.stats;
1487
+ },
1488
+ getActivity: async (limit = 50) => {
1489
+ logger.log("info", "api", "Fetching activity", { limit });
1490
+ const response = await apiRequest(
1491
+ `/nexus/activity?workspaceId=${workspaceId}&limit=${limit}`
1492
+ );
1493
+ return response.activities;
1494
+ },
1495
+ getLabels: async () => {
1496
+ logger.log("info", "api", "Fetching labels");
1497
+ const response = await apiRequest(
1498
+ `/nexus/labels?workspaceId=${workspaceId}`
1499
+ );
1500
+ return response.labels;
1501
+ },
1502
+ applyLabel: async (itemIds, labelId) => {
1503
+ logger.log("info", "api", "Applying label", { count: itemIds.length, labelId });
1504
+ await apiRequest("/nexus/labels/apply", {
1505
+ method: "POST",
1506
+ body: JSON.stringify({ itemIds, labelId })
1507
+ });
1508
+ postMessage("sybil:nexus:refresh");
1509
+ },
1510
+ removeLabel: async (itemIds, labelId) => {
1511
+ logger.log("info", "api", "Removing label", { count: itemIds.length, labelId });
1512
+ await apiRequest("/nexus/labels/apply", {
1513
+ method: "DELETE",
1514
+ body: JSON.stringify({ itemIds, labelId })
1515
+ });
1516
+ postMessage("sybil:nexus:refresh");
1517
+ },
1518
+ setTheme: (newTheme) => {
1519
+ logger.log("debug", "ui", "Setting theme", { theme: newTheme });
1520
+ postMessage("sybil:nexus:setTheme", { theme: newTheme });
1521
+ },
1522
+ destroy: () => {
1523
+ logger.log("info", "ui", "Destroying Nexus embed");
1524
+ window.removeEventListener("message", handleMessage);
1525
+ iframe.remove();
1526
+ },
1527
+ getLogs: () => logger.getLogs(),
1528
+ clearLogs: () => logger.clearLogs()
1529
+ };
1530
+ return instance;
1531
+ }
1532
+ var NexusClient = class {
1533
+ constructor(config) {
1534
+ this.apiKey = config.apiKey;
1535
+ this.workspaceId = config.workspaceId;
1536
+ this.baseUrl = config.baseUrl || DEFAULT_BASE_URL3;
1537
+ this.logger = new NexusLogger(config.logging);
1538
+ }
1539
+ async request(endpoint, options = {}) {
1540
+ const url = `${this.baseUrl}/api/sdk/v1${endpoint}`;
1541
+ const startTime = Date.now();
1542
+ this.logger.log("debug", "api", `Request: ${options.method || "GET"} ${endpoint}`);
1543
+ const response = await fetch(url, {
1544
+ ...options,
1545
+ headers: {
1546
+ "x-api-key": this.apiKey,
1547
+ ...options.body instanceof FormData ? {} : { "Content-Type": "application/json" },
1548
+ ...options.headers
1549
+ }
1550
+ });
1551
+ const duration = Date.now() - startTime;
1552
+ if (!response.ok) {
1553
+ const errorData = await response.json().catch(() => ({}));
1554
+ this.logger.log("error", "api", `Request failed: ${endpoint}`, {
1555
+ status: response.status,
1556
+ error: errorData
1557
+ }, duration);
1558
+ throw new Error(errorData.error?.message || `Request failed with status ${response.status}`);
1559
+ }
1560
+ this.logger.log("debug", "api", `Response: ${endpoint}`, { status: response.status }, duration);
1561
+ return response.json();
1562
+ }
1563
+ async listFiles(folderId) {
1564
+ const params = new URLSearchParams({ workspaceId: this.workspaceId });
1565
+ if (folderId !== void 0) params.set("folderId", folderId || "null");
1566
+ const response = await this.request(`/nexus/files?${params.toString()}`);
1567
+ return response.files;
1568
+ }
1569
+ async listFolders(parentId) {
1570
+ const params = new URLSearchParams({ workspaceId: this.workspaceId });
1571
+ if (parentId !== void 0) params.set("parentId", parentId || "null");
1572
+ const response = await this.request(`/nexus/folders?${params.toString()}`);
1573
+ return response.folders;
1574
+ }
1575
+ async getFolderContents(folderId) {
1576
+ const params = new URLSearchParams({ workspaceId: this.workspaceId });
1577
+ if (folderId) params.set("folderId", folderId);
1578
+ return this.request(`/nexus/folders/contents?${params.toString()}`);
1579
+ }
1580
+ async getFile(fileId) {
1581
+ const response = await this.request(`/nexus/files/${fileId}`);
1582
+ return response.file;
1583
+ }
1584
+ async uploadFile(file, folderId) {
1585
+ const formData = new FormData();
1586
+ formData.append("file", file);
1587
+ formData.append("workspaceId", this.workspaceId);
1588
+ if (folderId) formData.append("folderId", folderId);
1589
+ const response = await fetch(`${this.baseUrl}/api/sdk/v1/nexus/upload`, {
1590
+ method: "POST",
1591
+ headers: { "x-api-key": this.apiKey },
1592
+ body: formData
1593
+ });
1594
+ if (!response.ok) throw new Error("Failed to upload file");
1595
+ const data = await response.json();
1596
+ return data.file;
1597
+ }
1598
+ async deleteFile(fileId) {
1599
+ await this.request(`/nexus/files/${fileId}`, { method: "DELETE" });
1600
+ }
1601
+ async createFolder(name, parentId) {
1602
+ const response = await this.request("/nexus/folders", {
1603
+ method: "POST",
1604
+ body: JSON.stringify({ workspaceId: this.workspaceId, name, parentId })
1605
+ });
1606
+ return response.folder;
1607
+ }
1608
+ async deleteFolder(folderId) {
1609
+ await this.request(`/nexus/folders/${folderId}`, { method: "DELETE" });
1610
+ }
1611
+ async getStats() {
1612
+ const response = await this.request(
1613
+ `/nexus/stats?workspaceId=${this.workspaceId}`
1614
+ );
1615
+ return response.stats;
1616
+ }
1617
+ async getActivity(limit = 50) {
1618
+ const response = await this.request(
1619
+ `/nexus/activity?workspaceId=${this.workspaceId}&limit=${limit}`
1620
+ );
1621
+ return response.activities;
1622
+ }
1623
+ getLogs() {
1624
+ return this.logger.getLogs();
1625
+ }
1626
+ clearLogs() {
1627
+ this.logger.clearLogs();
1628
+ }
1629
+ };
1630
+
1631
+ // src/react/SybilNexus.tsx
1632
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1633
+ var SybilNexus = (0, import_react3.forwardRef)(function SybilNexus2({
1634
+ apiKey,
1635
+ workspaceId,
1636
+ baseUrl,
1637
+ theme = "dark",
1638
+ initialFolderId = null,
1639
+ viewMode = "list",
1640
+ showSidebar = true,
1641
+ showActivityFeed = true,
1642
+ showBreadcrumbs = true,
1643
+ showSearch = true,
1644
+ allowUpload = true,
1645
+ allowDownload = true,
1646
+ allowDelete = true,
1647
+ allowMove = true,
1648
+ allowRename = true,
1649
+ allowCreateFolder = true,
1650
+ allowMultiSelect = true,
1651
+ maxUploadSize,
1652
+ acceptedFileTypes,
1653
+ features,
1654
+ logging,
1655
+ className,
1656
+ style,
1657
+ onReady,
1658
+ onNavigate,
1659
+ onFileSelect,
1660
+ onFileOpen,
1661
+ onFileUpload,
1662
+ onFileDelete,
1663
+ onFolderCreate,
1664
+ onFolderDelete,
1665
+ onSelectionChange,
1666
+ onError
1667
+ }, ref) {
1668
+ const containerRef = (0, import_react3.useRef)(null);
1669
+ const instanceRef = (0, import_react3.useRef)(null);
1670
+ (0, import_react3.useImperativeHandle)(ref, () => ({
1671
+ getFiles: async (folderId) => {
1672
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1673
+ return instanceRef.current.getFiles(folderId);
1674
+ },
1675
+ getFolders: async (parentId) => {
1676
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1677
+ return instanceRef.current.getFolders(parentId);
1678
+ },
1679
+ getFolderContents: async (folderId) => {
1680
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1681
+ return instanceRef.current.getFolderContents(folderId);
1682
+ },
1683
+ getFolderTree: async () => {
1684
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1685
+ return instanceRef.current.getFolderTree();
1686
+ },
1687
+ getFile: async (fileId) => {
1688
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1689
+ return instanceRef.current.getFile(fileId);
1690
+ },
1691
+ getFolder: async (folderId) => {
1692
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1693
+ return instanceRef.current.getFolder(folderId);
1694
+ },
1695
+ uploadFile: async (file, folderId, onProgress) => {
1696
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1697
+ return instanceRef.current.uploadFile(file, folderId, onProgress);
1698
+ },
1699
+ uploadFiles: async (files, folderId, onProgress) => {
1700
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1701
+ return instanceRef.current.uploadFiles(files, folderId, onProgress);
1702
+ },
1703
+ downloadFile: async (fileId) => {
1704
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1705
+ return instanceRef.current.downloadFile(fileId);
1706
+ },
1707
+ getDownloadUrl: async (fileId) => {
1708
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1709
+ return instanceRef.current.getDownloadUrl(fileId);
1710
+ },
1711
+ deleteFile: async (fileId) => {
1712
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1713
+ return instanceRef.current.deleteFile(fileId);
1714
+ },
1715
+ deleteFiles: async (fileIds) => {
1716
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1717
+ return instanceRef.current.deleteFiles(fileIds);
1718
+ },
1719
+ moveFile: async (fileId, targetFolderId) => {
1720
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1721
+ return instanceRef.current.moveFile(fileId, targetFolderId);
1722
+ },
1723
+ renameFile: async (fileId, newName) => {
1724
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1725
+ return instanceRef.current.renameFile(fileId, newName);
1726
+ },
1727
+ starFile: async (fileId, starred) => {
1728
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1729
+ return instanceRef.current.starFile(fileId, starred);
1730
+ },
1731
+ createFolder: async (name, parentId, options) => {
1732
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1733
+ return instanceRef.current.createFolder(name, parentId, options);
1734
+ },
1735
+ deleteFolder: async (folderId) => {
1736
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1737
+ return instanceRef.current.deleteFolder(folderId);
1738
+ },
1739
+ moveFolder: async (folderId, targetParentId) => {
1740
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1741
+ return instanceRef.current.moveFolder(folderId, targetParentId);
1742
+ },
1743
+ renameFolder: async (folderId, newName) => {
1744
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1745
+ return instanceRef.current.renameFolder(folderId, newName);
1746
+ },
1747
+ navigateTo: (folderId) => {
1748
+ instanceRef.current?.navigateTo(folderId);
1749
+ },
1750
+ getCurrentFolder: () => {
1751
+ return instanceRef.current?.getCurrentFolder() || null;
1752
+ },
1753
+ getSelection: () => {
1754
+ return instanceRef.current?.getSelection() || [];
1755
+ },
1756
+ setSelection: (itemIds) => {
1757
+ instanceRef.current?.setSelection(itemIds);
1758
+ },
1759
+ clearSelection: () => {
1760
+ instanceRef.current?.clearSelection();
1761
+ },
1762
+ selectAll: () => {
1763
+ instanceRef.current?.selectAll();
1764
+ },
1765
+ setViewMode: (mode) => {
1766
+ instanceRef.current?.setViewMode(mode);
1767
+ },
1768
+ toggleActivityFeed: () => {
1769
+ instanceRef.current?.toggleActivityFeed();
1770
+ },
1771
+ toggleSidebar: () => {
1772
+ instanceRef.current?.toggleSidebar();
1773
+ },
1774
+ refresh: async () => {
1775
+ return instanceRef.current?.refresh();
1776
+ },
1777
+ search: async (query) => {
1778
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1779
+ return instanceRef.current.search(query);
1780
+ },
1781
+ getStats: async () => {
1782
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1783
+ return instanceRef.current.getStats();
1784
+ },
1785
+ getActivity: async (limit) => {
1786
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1787
+ return instanceRef.current.getActivity(limit);
1788
+ },
1789
+ getLabels: async () => {
1790
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1791
+ return instanceRef.current.getLabels();
1792
+ },
1793
+ applyLabel: async (itemIds, labelId) => {
1794
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1795
+ return instanceRef.current.applyLabel(itemIds, labelId);
1796
+ },
1797
+ removeLabel: async (itemIds, labelId) => {
1798
+ if (!instanceRef.current) throw new Error("Nexus not initialized");
1799
+ return instanceRef.current.removeLabel(itemIds, labelId);
1800
+ },
1801
+ setTheme: (newTheme) => {
1802
+ instanceRef.current?.setTheme(newTheme);
1803
+ },
1804
+ getLogs: () => {
1805
+ return instanceRef.current?.getLogs() || [];
1806
+ },
1807
+ clearLogs: () => {
1808
+ instanceRef.current?.clearLogs();
1809
+ }
1810
+ }));
1811
+ (0, import_react3.useEffect)(() => {
1812
+ if (!containerRef.current || !apiKey || !workspaceId) return;
1813
+ instanceRef.current?.destroy();
1814
+ const config = {
1815
+ apiKey,
1816
+ workspaceId,
1817
+ container: containerRef.current,
1818
+ baseUrl,
1819
+ theme,
1820
+ initialFolderId,
1821
+ viewMode,
1822
+ showSidebar,
1823
+ showActivityFeed,
1824
+ showBreadcrumbs,
1825
+ showSearch,
1826
+ allowUpload,
1827
+ allowDownload,
1828
+ allowDelete,
1829
+ allowMove,
1830
+ allowRename,
1831
+ allowCreateFolder,
1832
+ allowMultiSelect,
1833
+ maxUploadSize,
1834
+ acceptedFileTypes,
1835
+ features,
1836
+ logging,
1837
+ onReady,
1838
+ onNavigate,
1839
+ onFileSelect,
1840
+ onFileOpen,
1841
+ onFileUpload,
1842
+ onFileDelete,
1843
+ onFolderCreate,
1844
+ onFolderDelete,
1845
+ onSelectionChange,
1846
+ onError
1847
+ };
1848
+ instanceRef.current = embedNexus(config);
1849
+ return () => {
1850
+ instanceRef.current?.destroy();
1851
+ instanceRef.current = null;
1852
+ };
1853
+ }, [apiKey, workspaceId, baseUrl]);
1854
+ (0, import_react3.useEffect)(() => {
1855
+ instanceRef.current?.setTheme(theme);
1856
+ }, [theme]);
1857
+ (0, import_react3.useEffect)(() => {
1858
+ instanceRef.current?.setViewMode(viewMode);
1859
+ }, [viewMode]);
1860
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1861
+ "div",
1862
+ {
1863
+ ref: containerRef,
1864
+ className,
1865
+ style: {
1866
+ width: "100%",
1867
+ height: "100%",
1868
+ minHeight: "500px",
1869
+ ...style
1870
+ }
1871
+ }
1872
+ );
1873
+ });
1874
+
1875
+ // src/react/hooks.ts
1876
+ var import_react4 = require("react");
1877
+ function useSybilPages(options) {
1878
+ const { apiKey, baseUrl } = options;
1879
+ const [page, setPage] = (0, import_react4.useState)(null);
1880
+ const [loading, setLoading] = (0, import_react4.useState)(false);
1881
+ const [saving, setSaving] = (0, import_react4.useState)(false);
1882
+ const [error, setError] = (0, import_react4.useState)(null);
1883
+ const sdkRef = (0, import_react4.useRef)(null);
1884
+ const pendingBlocksRef = (0, import_react4.useRef)(null);
1885
+ (0, import_react4.useEffect)(() => {
1886
+ sdkRef.current = new SybilSDK({
1887
+ apiKey,
1888
+ baseUrl: baseUrl ? `${baseUrl}/api/sdk/v1` : void 0
1889
+ });
1890
+ }, [apiKey, baseUrl]);
1891
+ const fetchPage = (0, import_react4.useCallback)(async (pageId) => {
1892
+ if (!sdkRef.current) return;
1893
+ setLoading(true);
1894
+ setError(null);
1895
+ try {
1896
+ const { page: fetchedPage } = await sdkRef.current.pages.get(pageId);
1897
+ setPage(fetchedPage);
1898
+ } catch (err) {
1899
+ setError(err instanceof Error ? err : new Error("Failed to fetch page"));
1900
+ } finally {
1901
+ setLoading(false);
1902
+ }
1903
+ }, []);
1904
+ const createPage = (0, import_react4.useCallback)(async (params = {}) => {
1905
+ if (!sdkRef.current) throw new Error("SDK not initialized");
1906
+ setLoading(true);
1907
+ setError(null);
1908
+ try {
1909
+ const { page: newPage } = await sdkRef.current.pages.create(params);
1910
+ setPage(newPage);
1911
+ return newPage;
1912
+ } catch (err) {
1913
+ const error2 = err instanceof Error ? err : new Error("Failed to create page");
1914
+ setError(error2);
1915
+ throw error2;
1916
+ } finally {
1917
+ setLoading(false);
1918
+ }
1919
+ }, []);
1920
+ const updatePage = (0, import_react4.useCallback)(async (pageId, params) => {
1921
+ if (!sdkRef.current) throw new Error("SDK not initialized");
1922
+ setSaving(true);
1923
+ setError(null);
1924
+ try {
1925
+ const { page: updatedPage } = await sdkRef.current.pages.update(pageId, params);
1926
+ setPage(updatedPage);
1927
+ return updatedPage;
1928
+ } catch (err) {
1929
+ const error2 = err instanceof Error ? err : new Error("Failed to update page");
1930
+ setError(error2);
1931
+ throw error2;
1932
+ } finally {
1933
+ setSaving(false);
1934
+ }
1935
+ }, []);
1936
+ const deletePage = (0, import_react4.useCallback)(async (pageId) => {
1937
+ if (!sdkRef.current) throw new Error("SDK not initialized");
1938
+ setLoading(true);
1939
+ setError(null);
1940
+ try {
1941
+ await sdkRef.current.pages.delete(pageId);
1942
+ setPage(null);
1943
+ } catch (err) {
1944
+ const error2 = err instanceof Error ? err : new Error("Failed to delete page");
1945
+ setError(error2);
1946
+ throw error2;
1947
+ } finally {
1948
+ setLoading(false);
1949
+ }
1950
+ }, []);
1951
+ const setBlocks = (0, import_react4.useCallback)((blocks) => {
1952
+ pendingBlocksRef.current = blocks;
1953
+ setPage((prev) => prev ? { ...prev, blocks } : null);
1954
+ }, []);
1955
+ const save = (0, import_react4.useCallback)(async () => {
1956
+ if (!page || !sdkRef.current || !pendingBlocksRef.current) return;
1957
+ await updatePage(page.id, { blocks: pendingBlocksRef.current });
1958
+ pendingBlocksRef.current = null;
1959
+ }, [page, updatePage]);
1960
+ return {
1961
+ page,
1962
+ loading,
1963
+ saving,
1964
+ error,
1965
+ fetchPage,
1966
+ createPage,
1967
+ updatePage,
1968
+ deletePage,
1969
+ setBlocks,
1970
+ save
1971
+ };
1972
+ }
1973
+
1974
+ // src/react/hooks/useAtlas.ts
1975
+ var import_react5 = require("react");
1976
+ function useAtlas(options) {
1977
+ const { apiKey, workspaceId, baseUrl, logging } = options;
1978
+ const [sidebar, setSidebar] = (0, import_react5.useState)(null);
1979
+ const [currentPage, setCurrentPage] = (0, import_react5.useState)(null);
1980
+ const [loading, setLoading] = (0, import_react5.useState)(false);
1981
+ const [saving, setSaving] = (0, import_react5.useState)(false);
1982
+ const [error, setError] = (0, import_react5.useState)(null);
1983
+ const clientRef = (0, import_react5.useRef)(null);
1984
+ (0, import_react5.useEffect)(() => {
1985
+ clientRef.current = new AtlasClient({
1986
+ apiKey,
1987
+ workspaceId,
1988
+ baseUrl,
1989
+ logging
1990
+ });
1991
+ }, [apiKey, workspaceId, baseUrl, logging]);
1992
+ const fetchSidebar = (0, import_react5.useCallback)(async () => {
1993
+ if (!clientRef.current) throw new Error("Client not initialized");
1994
+ setLoading(true);
1995
+ setError(null);
1996
+ try {
1997
+ const data = await clientRef.current.getSidebar();
1998
+ setSidebar(data);
1999
+ return data;
2000
+ } catch (err) {
2001
+ const error2 = err instanceof Error ? err : new Error("Failed to fetch sidebar");
2002
+ setError(error2);
2003
+ throw error2;
2004
+ } finally {
2005
+ setLoading(false);
2006
+ }
2007
+ }, []);
2008
+ const fetchPage = (0, import_react5.useCallback)(async (pageId) => {
2009
+ if (!clientRef.current) throw new Error("Client not initialized");
2010
+ setLoading(true);
2011
+ setError(null);
2012
+ try {
2013
+ const page = await clientRef.current.getPage(pageId);
2014
+ setCurrentPage(page);
2015
+ return page;
2016
+ } catch (err) {
2017
+ const error2 = err instanceof Error ? err : new Error("Failed to fetch page");
2018
+ setError(error2);
2019
+ throw error2;
2020
+ } finally {
2021
+ setLoading(false);
2022
+ }
2023
+ }, []);
2024
+ const createPage = (0, import_react5.useCallback)(async (params = {}) => {
2025
+ if (!clientRef.current) throw new Error("Client not initialized");
2026
+ setSaving(true);
2027
+ setError(null);
2028
+ try {
2029
+ const page = await clientRef.current.createPage(params);
2030
+ await fetchSidebar();
2031
+ return page;
2032
+ } catch (err) {
2033
+ const error2 = err instanceof Error ? err : new Error("Failed to create page");
2034
+ setError(error2);
2035
+ throw error2;
2036
+ } finally {
2037
+ setSaving(false);
2038
+ }
2039
+ }, [fetchSidebar]);
2040
+ const updatePage = (0, import_react5.useCallback)(async (pageId, params) => {
2041
+ if (!clientRef.current) throw new Error("Client not initialized");
2042
+ setSaving(true);
2043
+ setError(null);
2044
+ try {
2045
+ const page = await clientRef.current.updatePage(pageId, params);
2046
+ setCurrentPage(page);
2047
+ await fetchSidebar();
2048
+ return page;
2049
+ } catch (err) {
2050
+ const error2 = err instanceof Error ? err : new Error("Failed to update page");
2051
+ setError(error2);
2052
+ throw error2;
2053
+ } finally {
2054
+ setSaving(false);
2055
+ }
2056
+ }, [fetchSidebar]);
2057
+ const deletePage = (0, import_react5.useCallback)(async (pageId) => {
2058
+ if (!clientRef.current) throw new Error("Client not initialized");
2059
+ setSaving(true);
2060
+ setError(null);
2061
+ try {
2062
+ await clientRef.current.deletePage(pageId);
2063
+ if (currentPage?.id === pageId) {
2064
+ setCurrentPage(null);
2065
+ }
2066
+ await fetchSidebar();
2067
+ } catch (err) {
2068
+ const error2 = err instanceof Error ? err : new Error("Failed to delete page");
2069
+ setError(error2);
2070
+ throw error2;
2071
+ } finally {
2072
+ setSaving(false);
2073
+ }
2074
+ }, [currentPage, fetchSidebar]);
2075
+ const toggleFavorite = (0, import_react5.useCallback)(async (pageId) => {
2076
+ if (!clientRef.current) throw new Error("Client not initialized");
2077
+ try {
2078
+ const page = await clientRef.current.toggleFavorite(pageId);
2079
+ if (currentPage?.id === pageId) {
2080
+ setCurrentPage(page);
2081
+ }
2082
+ await fetchSidebar();
2083
+ return page;
2084
+ } catch (err) {
2085
+ const error2 = err instanceof Error ? err : new Error("Failed to toggle favorite");
2086
+ setError(error2);
2087
+ throw error2;
2088
+ }
2089
+ }, [currentPage, fetchSidebar]);
2090
+ const exportPage = (0, import_react5.useCallback)(async (pageId, format) => {
2091
+ if (!clientRef.current) throw new Error("Client not initialized");
2092
+ setLoading(true);
2093
+ try {
2094
+ return await clientRef.current.exportPage(pageId, format);
2095
+ } catch (err) {
2096
+ const error2 = err instanceof Error ? err : new Error("Failed to export page");
2097
+ setError(error2);
2098
+ throw error2;
2099
+ } finally {
2100
+ setLoading(false);
2101
+ }
2102
+ }, []);
2103
+ const getLogs = (0, import_react5.useCallback)(() => {
2104
+ return clientRef.current?.getLogs() || [];
2105
+ }, []);
2106
+ const clearLogs = (0, import_react5.useCallback)(() => {
2107
+ clientRef.current?.clearLogs();
2108
+ }, []);
2109
+ return {
2110
+ sidebar,
2111
+ currentPage,
2112
+ loading,
2113
+ saving,
2114
+ error,
2115
+ fetchSidebar,
2116
+ fetchPage,
2117
+ createPage,
2118
+ updatePage,
2119
+ deletePage,
2120
+ toggleFavorite,
2121
+ exportPage,
2122
+ setCurrentPage,
2123
+ getLogs,
2124
+ clearLogs
2125
+ };
2126
+ }
2127
+
2128
+ // src/react/hooks/useNexus.ts
2129
+ var import_react6 = require("react");
2130
+ function useNexus(options) {
2131
+ const { apiKey, workspaceId, baseUrl, logging } = options;
2132
+ const [files, setFiles] = (0, import_react6.useState)([]);
2133
+ const [folders, setFolders] = (0, import_react6.useState)([]);
2134
+ const [currentFolder, setCurrentFolder] = (0, import_react6.useState)(null);
2135
+ const [breadcrumb, setBreadcrumb] = (0, import_react6.useState)([]);
2136
+ const [loading, setLoading] = (0, import_react6.useState)(false);
2137
+ const [uploading, setUploading] = (0, import_react6.useState)(false);
2138
+ const [uploadProgress, setUploadProgress] = (0, import_react6.useState)(0);
2139
+ const [error, setError] = (0, import_react6.useState)(null);
2140
+ const clientRef = (0, import_react6.useRef)(null);
2141
+ (0, import_react6.useEffect)(() => {
2142
+ clientRef.current = new NexusClient({
2143
+ apiKey,
2144
+ workspaceId,
2145
+ baseUrl,
2146
+ logging
2147
+ });
2148
+ }, [apiKey, workspaceId, baseUrl, logging]);
2149
+ const fetchFiles = (0, import_react6.useCallback)(async (folderId) => {
2150
+ if (!clientRef.current) throw new Error("Client not initialized");
2151
+ setLoading(true);
2152
+ setError(null);
2153
+ try {
2154
+ const data = await clientRef.current.listFiles(folderId);
2155
+ setFiles(data);
2156
+ return data;
2157
+ } catch (err) {
2158
+ const error2 = err instanceof Error ? err : new Error("Failed to fetch files");
2159
+ setError(error2);
2160
+ throw error2;
2161
+ } finally {
2162
+ setLoading(false);
2163
+ }
2164
+ }, []);
2165
+ const fetchFolders = (0, import_react6.useCallback)(async (parentId) => {
2166
+ if (!clientRef.current) throw new Error("Client not initialized");
2167
+ setLoading(true);
2168
+ setError(null);
2169
+ try {
2170
+ const data = await clientRef.current.listFolders(parentId);
2171
+ setFolders(data);
2172
+ return data;
2173
+ } catch (err) {
2174
+ const error2 = err instanceof Error ? err : new Error("Failed to fetch folders");
2175
+ setError(error2);
2176
+ throw error2;
2177
+ } finally {
2178
+ setLoading(false);
2179
+ }
2180
+ }, []);
2181
+ const fetchFolderContents = (0, import_react6.useCallback)(async (folderId) => {
2182
+ if (!clientRef.current) throw new Error("Client not initialized");
2183
+ setLoading(true);
2184
+ setError(null);
2185
+ try {
2186
+ const data = await clientRef.current.getFolderContents(folderId);
2187
+ setBreadcrumb(data.breadcrumb);
2188
+ setCurrentFolder(folderId || null);
2189
+ return data;
2190
+ } catch (err) {
2191
+ const error2 = err instanceof Error ? err : new Error("Failed to fetch folder contents");
2192
+ setError(error2);
2193
+ throw error2;
2194
+ } finally {
2195
+ setLoading(false);
2196
+ }
2197
+ }, []);
2198
+ const getFile = (0, import_react6.useCallback)(async (fileId) => {
2199
+ if (!clientRef.current) throw new Error("Client not initialized");
2200
+ setLoading(true);
2201
+ setError(null);
2202
+ try {
2203
+ return await clientRef.current.getFile(fileId);
2204
+ } catch (err) {
2205
+ const error2 = err instanceof Error ? err : new Error("Failed to get file");
2206
+ setError(error2);
2207
+ throw error2;
2208
+ } finally {
2209
+ setLoading(false);
2210
+ }
2211
+ }, []);
2212
+ const uploadFile = (0, import_react6.useCallback)(async (file, folderId) => {
2213
+ if (!clientRef.current) throw new Error("Client not initialized");
2214
+ setUploading(true);
2215
+ setUploadProgress(0);
2216
+ setError(null);
2217
+ try {
2218
+ const result = await clientRef.current.uploadFile(file, folderId);
2219
+ await fetchFiles(folderId);
2220
+ return result;
2221
+ } catch (err) {
2222
+ const error2 = err instanceof Error ? err : new Error("Failed to upload file");
2223
+ setError(error2);
2224
+ throw error2;
2225
+ } finally {
2226
+ setUploading(false);
2227
+ setUploadProgress(0);
2228
+ }
2229
+ }, [fetchFiles]);
2230
+ const uploadFiles = (0, import_react6.useCallback)(async (filesToUpload, folderId) => {
2231
+ if (!clientRef.current) throw new Error("Client not initialized");
2232
+ setUploading(true);
2233
+ setUploadProgress(0);
2234
+ setError(null);
2235
+ const results = [];
2236
+ try {
2237
+ for (let i = 0; i < filesToUpload.length; i++) {
2238
+ const result = await clientRef.current.uploadFile(filesToUpload[i], folderId);
2239
+ results.push(result);
2240
+ setUploadProgress((i + 1) / filesToUpload.length * 100);
2241
+ }
2242
+ await fetchFiles(folderId);
2243
+ return results;
2244
+ } catch (err) {
2245
+ const error2 = err instanceof Error ? err : new Error("Failed to upload files");
2246
+ setError(error2);
2247
+ throw error2;
2248
+ } finally {
2249
+ setUploading(false);
2250
+ setUploadProgress(0);
2251
+ }
2252
+ }, [fetchFiles]);
2253
+ const deleteFile = (0, import_react6.useCallback)(async (fileId) => {
2254
+ if (!clientRef.current) throw new Error("Client not initialized");
2255
+ setLoading(true);
2256
+ setError(null);
2257
+ try {
2258
+ await clientRef.current.deleteFile(fileId);
2259
+ await fetchFiles(currentFolder);
2260
+ } catch (err) {
2261
+ const error2 = err instanceof Error ? err : new Error("Failed to delete file");
2262
+ setError(error2);
2263
+ throw error2;
2264
+ } finally {
2265
+ setLoading(false);
2266
+ }
2267
+ }, [currentFolder, fetchFiles]);
2268
+ const createFolder = (0, import_react6.useCallback)(async (name, parentId) => {
2269
+ if (!clientRef.current) throw new Error("Client not initialized");
2270
+ setLoading(true);
2271
+ setError(null);
2272
+ try {
2273
+ const result = await clientRef.current.createFolder(name, parentId);
2274
+ await fetchFolders(parentId);
2275
+ return result;
2276
+ } catch (err) {
2277
+ const error2 = err instanceof Error ? err : new Error("Failed to create folder");
2278
+ setError(error2);
2279
+ throw error2;
2280
+ } finally {
2281
+ setLoading(false);
2282
+ }
2283
+ }, [fetchFolders]);
2284
+ const deleteFolder = (0, import_react6.useCallback)(async (folderId) => {
2285
+ if (!clientRef.current) throw new Error("Client not initialized");
2286
+ setLoading(true);
2287
+ setError(null);
2288
+ try {
2289
+ await clientRef.current.deleteFolder(folderId);
2290
+ await fetchFolders(currentFolder);
2291
+ } catch (err) {
2292
+ const error2 = err instanceof Error ? err : new Error("Failed to delete folder");
2293
+ setError(error2);
2294
+ throw error2;
2295
+ } finally {
2296
+ setLoading(false);
2297
+ }
2298
+ }, [currentFolder, fetchFolders]);
2299
+ const navigateTo = (0, import_react6.useCallback)((folderId) => {
2300
+ setCurrentFolder(folderId);
2301
+ fetchFolderContents(folderId);
2302
+ }, [fetchFolderContents]);
2303
+ const getStats = (0, import_react6.useCallback)(async () => {
2304
+ if (!clientRef.current) throw new Error("Client not initialized");
2305
+ return clientRef.current.getStats();
2306
+ }, []);
2307
+ const getActivity = (0, import_react6.useCallback)(async (limit) => {
2308
+ if (!clientRef.current) throw new Error("Client not initialized");
2309
+ return clientRef.current.getActivity(limit);
2310
+ }, []);
2311
+ const refresh = (0, import_react6.useCallback)(async () => {
2312
+ await fetchFolderContents(currentFolder);
2313
+ }, [currentFolder, fetchFolderContents]);
2314
+ const getLogs = (0, import_react6.useCallback)(() => {
2315
+ return clientRef.current?.getLogs() || [];
2316
+ }, []);
2317
+ const clearLogs = (0, import_react6.useCallback)(() => {
2318
+ clientRef.current?.clearLogs();
2319
+ }, []);
2320
+ return {
2321
+ files,
2322
+ folders,
2323
+ currentFolder,
2324
+ breadcrumb,
2325
+ loading,
2326
+ uploading,
2327
+ uploadProgress,
2328
+ error,
2329
+ fetchFiles,
2330
+ fetchFolders,
2331
+ fetchFolderContents,
2332
+ getFile,
2333
+ uploadFile,
2334
+ uploadFiles,
2335
+ deleteFile,
2336
+ createFolder,
2337
+ deleteFolder,
2338
+ navigateTo,
2339
+ getStats,
2340
+ getActivity,
2341
+ refresh,
2342
+ getLogs,
2343
+ clearLogs
2344
+ };
2345
+ }
2346
+ // Annotate the CommonJS export names for ESM import in node:
2347
+ 0 && (module.exports = {
2348
+ SybilAtlas,
2349
+ SybilNexus,
2350
+ SybilPages,
2351
+ useAtlas,
2352
+ useNexus,
2353
+ useSybilPages
2354
+ });