lyzr-cortex-sdk 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,434 @@
1
+ import { createContext, useState, useMemo, useEffect, useCallback, useContext } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ // src/provider.tsx
5
+
6
+ // src/bridge.ts
7
+ var CortexBridge = class {
8
+ constructor() {
9
+ this.handlers = /* @__PURE__ */ new Map();
10
+ this.parentOrigin = null;
11
+ this._isReady = false;
12
+ this._user = null;
13
+ this._theme = "light";
14
+ this.readyResolve = null;
15
+ this._isEmbedded = typeof window !== "undefined" && window.self !== window.top;
16
+ this.readyPromise = new Promise((resolve) => {
17
+ this.readyResolve = resolve;
18
+ });
19
+ if (this._isEmbedded && typeof window !== "undefined") {
20
+ window.addEventListener("message", this.handleMessage.bind(this));
21
+ this.sendToParent({ type: "TOOL_READY" });
22
+ setTimeout(() => {
23
+ if (this.readyResolve) {
24
+ this._isReady = true;
25
+ this.readyResolve(null);
26
+ this.readyResolve = null;
27
+ }
28
+ }, 5e3);
29
+ } else {
30
+ this._isReady = true;
31
+ if (this.readyResolve) {
32
+ this.readyResolve(null);
33
+ this.readyResolve = null;
34
+ }
35
+ }
36
+ }
37
+ /** Whether app is embedded in Cortex shell */
38
+ get isEmbedded() {
39
+ return this._isEmbedded;
40
+ }
41
+ /** Whether bridge is initialized */
42
+ get isReady() {
43
+ return this._isReady;
44
+ }
45
+ /** Current user from Cortex (null if standalone) */
46
+ get user() {
47
+ return this._user;
48
+ }
49
+ /** Current theme from Cortex */
50
+ get theme() {
51
+ return this._theme;
52
+ }
53
+ /**
54
+ * Wait for Cortex initialization.
55
+ * Resolves with user if embedded, null if standalone.
56
+ */
57
+ waitForReady() {
58
+ return this.readyPromise;
59
+ }
60
+ handleMessage(event) {
61
+ if (!this.parentOrigin) {
62
+ this.parentOrigin = event.origin;
63
+ } else if (event.origin !== this.parentOrigin) {
64
+ console.warn("CortexBridge: Rejected message from unexpected origin:", event.origin);
65
+ return;
66
+ }
67
+ const message = event.data;
68
+ if (!message || typeof message.type !== "string") return;
69
+ if (message.type === "CORTEX_INIT") {
70
+ const payload = message.payload;
71
+ this._user = payload?.user ?? null;
72
+ this._theme = payload?.theme ?? "light";
73
+ this._isReady = true;
74
+ if (this.readyResolve) {
75
+ this.readyResolve(this._user);
76
+ this.readyResolve = null;
77
+ }
78
+ }
79
+ if (message.type === "CORTEX_THEME") {
80
+ const payload = message.payload;
81
+ this._theme = payload?.theme ?? "light";
82
+ if (typeof document !== "undefined") {
83
+ document.documentElement.setAttribute("data-theme", this._theme);
84
+ }
85
+ }
86
+ const handlers = this.handlers.get(message.type) || [];
87
+ handlers.forEach((handler) => handler(message.payload));
88
+ }
89
+ /**
90
+ * Register a handler for a message type.
91
+ * Returns unsubscribe function.
92
+ */
93
+ on(messageType, handler) {
94
+ const handlers = this.handlers.get(messageType) || [];
95
+ handlers.push(handler);
96
+ this.handlers.set(messageType, handlers);
97
+ return () => {
98
+ const current = this.handlers.get(messageType) || [];
99
+ this.handlers.set(
100
+ messageType,
101
+ current.filter((h) => h !== handler)
102
+ );
103
+ };
104
+ }
105
+ /**
106
+ * Send a message to parent window (Cortex shell).
107
+ */
108
+ sendToParent(message) {
109
+ if (this._isEmbedded && typeof window !== "undefined") {
110
+ window.parent.postMessage(message, "*");
111
+ }
112
+ }
113
+ /**
114
+ * Open Cortex chat, optionally with a prefilled query.
115
+ */
116
+ openChat(prefilledQuery) {
117
+ this.sendToParent({
118
+ type: "OPEN_CHAT",
119
+ payload: { query: prefilledQuery }
120
+ });
121
+ }
122
+ /**
123
+ * Show a notification in Cortex shell.
124
+ */
125
+ showNotification(message, type = "info") {
126
+ this.sendToParent({
127
+ type: "SHOW_NOTIFICATION",
128
+ payload: { message, type }
129
+ });
130
+ }
131
+ /**
132
+ * Navigate to a path within Cortex.
133
+ */
134
+ navigate(path) {
135
+ this.sendToParent({
136
+ type: "NAVIGATE",
137
+ payload: { path }
138
+ });
139
+ }
140
+ /**
141
+ * Cleanup - remove message listener.
142
+ */
143
+ destroy() {
144
+ if (typeof window !== "undefined") {
145
+ window.removeEventListener("message", this.handleMessage.bind(this));
146
+ }
147
+ this.handlers.clear();
148
+ }
149
+ };
150
+ var bridgeInstance = null;
151
+ var noopBridge = {
152
+ isEmbedded: false,
153
+ isReady: true,
154
+ user: null,
155
+ theme: "light",
156
+ waitForReady: () => Promise.resolve(null),
157
+ on: () => () => {
158
+ },
159
+ sendToParent: () => {
160
+ },
161
+ openChat: () => {
162
+ },
163
+ showNotification: () => {
164
+ },
165
+ navigate: () => {
166
+ },
167
+ destroy: () => {
168
+ }
169
+ };
170
+ function getBridge() {
171
+ if (typeof window === "undefined") {
172
+ return noopBridge;
173
+ }
174
+ if (!bridgeInstance) {
175
+ bridgeInstance = new CortexBridge();
176
+ }
177
+ return bridgeInstance;
178
+ }
179
+ function isEmbeddedInCortex() {
180
+ return typeof window !== "undefined" && window.self !== window.top;
181
+ }
182
+
183
+ // src/client.ts
184
+ var CortexClient = class {
185
+ constructor(config = {}) {
186
+ this.apiUrl = config.apiUrl || "";
187
+ this.apiKey = config.apiKey || "";
188
+ this.toolId = config.toolId || "";
189
+ this.debug = config.debug || false;
190
+ }
191
+ /** Whether client is configured */
192
+ get isConfigured() {
193
+ return Boolean(this.apiUrl && this.apiKey);
194
+ }
195
+ log(...args) {
196
+ if (this.debug) {
197
+ console.log("[CortexClient]", ...args);
198
+ }
199
+ }
200
+ async request(method, path, body) {
201
+ if (!this.isConfigured) {
202
+ throw new Error("CortexClient not configured: missing apiUrl or apiKey");
203
+ }
204
+ const url = `${this.apiUrl.replace(/\/$/, "")}${path}`;
205
+ this.log(`${method} ${url}`, body);
206
+ const response = await fetch(url, {
207
+ method,
208
+ headers: {
209
+ "Content-Type": "application/json",
210
+ "X-API-Key": this.apiKey,
211
+ "X-Cortex-Tool-ID": this.toolId
212
+ },
213
+ body: body ? JSON.stringify(body) : void 0
214
+ });
215
+ if (!response.ok) {
216
+ const errorText = await response.text();
217
+ throw new Error(`Cortex API error (${response.status}): ${errorText}`);
218
+ }
219
+ return response.json();
220
+ }
221
+ /**
222
+ * Push a document to Cortex Knowledge Graph.
223
+ */
224
+ async push(doc) {
225
+ return this.request("POST", "/api/tools/documents", {
226
+ external_id: doc.id,
227
+ document_type: doc.type,
228
+ content: doc.content,
229
+ name: doc.name,
230
+ external_url: doc.externalUrl,
231
+ access_scope: doc.scope || "global",
232
+ scope_team_ids: doc.teamIds,
233
+ metadata: doc.metadata
234
+ });
235
+ }
236
+ /**
237
+ * Query Cortex Knowledge Graph.
238
+ */
239
+ async query(question, options = {}) {
240
+ const response = await this.request("POST", "/api/tools/query", {
241
+ query: question,
242
+ filters: options.filters,
243
+ time_range_days: options.timeRangeDays,
244
+ max_results: options.maxResults || 10,
245
+ user_email: options.userEmail
246
+ });
247
+ return {
248
+ answer: response.answer,
249
+ sources: response.sources,
250
+ query: response.query
251
+ };
252
+ }
253
+ /**
254
+ * Get user context from Cortex.
255
+ * Calls GET /api/tools/context/{userEmail}
256
+ */
257
+ async getUserContext(userEmail) {
258
+ try {
259
+ return await this.request(
260
+ "GET",
261
+ `/api/tools/context/${encodeURIComponent(userEmail)}`
262
+ );
263
+ } catch (error) {
264
+ if (error instanceof Error && error.message.includes("404")) {
265
+ return null;
266
+ }
267
+ throw error;
268
+ }
269
+ }
270
+ /**
271
+ * Share a document with another user.
272
+ * Calls POST /api/tools/share-document-for-user
273
+ *
274
+ * Creates a share record so the document appears in
275
+ * the recipient's "Shared with Me" at /personal/shared.
276
+ */
277
+ async shareDocument(params) {
278
+ return this.request("POST", "/api/tools/share-document-for-user", {
279
+ document_external_id: params.documentExternalId,
280
+ shared_by_email: params.sharedByEmail,
281
+ shared_with_email: params.sharedWithEmail,
282
+ document_name: params.documentName,
283
+ content: params.content,
284
+ external_url: params.externalUrl,
285
+ metadata: params.metadata
286
+ });
287
+ }
288
+ /**
289
+ * Get list of users in the tool's organization.
290
+ * Calls GET /api/tools/org-users-for-tool
291
+ */
292
+ async getOrgUsers(excludeEmail) {
293
+ const params = excludeEmail ? `?exclude_email=${encodeURIComponent(excludeEmail)}` : "";
294
+ return this.request("GET", `/api/tools/org-users-for-tool${params}`);
295
+ }
296
+ };
297
+ function createCortexClient(config) {
298
+ return new CortexClient(config);
299
+ }
300
+ var CortexContext = createContext(null);
301
+ function CortexProvider({
302
+ children,
303
+ apiUrl,
304
+ apiKey,
305
+ toolId,
306
+ debug = false
307
+ }) {
308
+ const [bridge] = useState(() => getBridge());
309
+ const [isReady, setIsReady] = useState(bridge.isReady);
310
+ const [user, setUser] = useState(bridge.user);
311
+ const [theme, setTheme] = useState(bridge.theme);
312
+ const client = useMemo(
313
+ () => new CortexClient({
314
+ apiUrl,
315
+ apiKey,
316
+ toolId,
317
+ debug
318
+ }),
319
+ [apiUrl, apiKey, toolId, debug]
320
+ );
321
+ useEffect(() => {
322
+ bridge.waitForReady().then((cortexUser) => {
323
+ setUser(cortexUser);
324
+ setIsReady(true);
325
+ setTheme(bridge.theme);
326
+ });
327
+ const unsubscribe = bridge.on(
328
+ "CORTEX_THEME",
329
+ (payload) => {
330
+ if (payload?.theme) {
331
+ setTheme(payload.theme);
332
+ }
333
+ }
334
+ );
335
+ return unsubscribe;
336
+ }, [bridge]);
337
+ const push = useCallback(
338
+ async (doc) => {
339
+ if (!client.isConfigured) {
340
+ if (debug) {
341
+ console.warn("CortexProvider: push called but API not configured");
342
+ }
343
+ return;
344
+ }
345
+ await client.push(doc);
346
+ },
347
+ [client, debug]
348
+ );
349
+ const query = useCallback(
350
+ async (question, options) => {
351
+ if (!client.isConfigured) {
352
+ if (debug) {
353
+ console.warn("CortexProvider: query called but API not configured");
354
+ }
355
+ return {
356
+ answer: "",
357
+ sources: [],
358
+ query: question
359
+ };
360
+ }
361
+ return client.query(question, {
362
+ ...options,
363
+ userEmail: user?.email
364
+ });
365
+ },
366
+ [client, user, debug]
367
+ );
368
+ const openChat = useCallback(
369
+ (prefilledQuery) => {
370
+ bridge.openChat(prefilledQuery);
371
+ },
372
+ [bridge]
373
+ );
374
+ const showNotification = useCallback(
375
+ (message, type) => {
376
+ bridge.showNotification(message, type);
377
+ },
378
+ [bridge]
379
+ );
380
+ const value = useMemo(
381
+ () => ({
382
+ user,
383
+ isEmbedded: bridge.isEmbedded,
384
+ isReady,
385
+ theme,
386
+ push,
387
+ query,
388
+ openChat,
389
+ showNotification
390
+ }),
391
+ [user, bridge.isEmbedded, isReady, theme, push, query, openChat, showNotification]
392
+ );
393
+ return /* @__PURE__ */ jsx(CortexContext.Provider, { value, children });
394
+ }
395
+ function useCortex() {
396
+ const context = useContext(CortexContext);
397
+ if (!context) {
398
+ return {
399
+ user: null,
400
+ isEmbedded: false,
401
+ isReady: true,
402
+ theme: "light",
403
+ push: async () => {
404
+ console.warn("useCortex: called outside CortexProvider");
405
+ },
406
+ query: async (q) => ({
407
+ answer: "",
408
+ sources: [],
409
+ query: q
410
+ }),
411
+ openChat: () => {
412
+ },
413
+ showNotification: () => {
414
+ }
415
+ };
416
+ }
417
+ return context;
418
+ }
419
+ function useIsEmbedded() {
420
+ const context = useContext(CortexContext);
421
+ return context?.isEmbedded ?? false;
422
+ }
423
+ function useCortexUser() {
424
+ const context = useContext(CortexContext);
425
+ return context?.user ?? null;
426
+ }
427
+ function useCortexTheme() {
428
+ const context = useContext(CortexContext);
429
+ return context?.theme ?? "light";
430
+ }
431
+
432
+ export { CortexBridge, CortexClient, CortexProvider, createCortexClient, getBridge, isEmbeddedInCortex, useCortex, useCortexTheme, useCortexUser, useIsEmbedded };
433
+ //# sourceMappingURL=index.mjs.map
434
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bridge.ts","../src/client.ts","../src/provider.tsx"],"names":[],"mappings":";;;;;;AAgDO,IAAM,eAAN,MAA4C;AAAA,EAUjD,WAAA,GAAc;AATd,IAAA,IAAA,CAAQ,QAAA,uBAA8C,GAAA,EAAI;AAC1D,IAAA,IAAA,CAAQ,YAAA,GAA8B,IAAA;AAEtC,IAAA,IAAA,CAAQ,QAAA,GAAoB,KAAA;AAC5B,IAAA,IAAA,CAAQ,KAAA,GAA2B,IAAA;AACnC,IAAA,IAAA,CAAQ,MAAA,GAA2B,OAAA;AAEnC,IAAA,IAAA,CAAQ,YAAA,GAA2D,IAAA;AAIjE,IAAA,IAAA,CAAK,cACH,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,SAAS,MAAA,CAAO,GAAA;AAG1D,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC3C,MAAA,IAAA,CAAK,YAAA,GAAe,OAAA;AAAA,IACtB,CAAC,CAAA;AAED,IAAA,IAAI,IAAA,CAAK,WAAA,IAAe,OAAO,MAAA,KAAW,WAAA,EAAa;AAErD,MAAA,MAAA,CAAO,iBAAiB,SAAA,EAAW,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA;AAGhE,MAAA,IAAA,CAAK,YAAA,CAAa,EAAE,IAAA,EAAM,YAAA,EAAc,CAAA;AAGxC,MAAA,UAAA,CAAW,MAAM;AACf,QAAA,IAAI,KAAK,YAAA,EAAc;AACrB,UAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,UAAA,IAAA,CAAK,aAAa,IAAI,CAAA;AACtB,UAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AAAA,QACtB;AAAA,MACF,GAAG,GAAI,CAAA;AAAA,IACT,CAAA,MAAO;AAEL,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,MAAA,IAAI,KAAK,YAAA,EAAc;AACrB,QAAA,IAAA,CAAK,aAAa,IAAI,CAAA;AACtB,QAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,UAAA,GAAsB;AACxB,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,OAAA,GAAmB;AACrB,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,IAAA,GAA0B;AAC5B,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,KAAA,GAA0B;AAC5B,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAA,GAA2C;AACzC,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA,EAEQ,cAAc,KAAA,EAAqB;AAEzC,IAAA,IAAI,CAAC,KAAK,YAAA,EAAc;AACtB,MAAA,IAAA,CAAK,eAAe,KAAA,CAAM,MAAA;AAAA,IAC5B,CAAA,MAAA,IAAW,KAAA,CAAM,MAAA,KAAW,IAAA,CAAK,YAAA,EAAc;AAC7C,MAAA,OAAA,CAAQ,IAAA,CAAK,wDAAA,EAA0D,KAAA,CAAM,MAAM,CAAA;AACnF,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAU,KAAA,CAAM,IAAA;AACtB,IAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,CAAQ,SAAS,QAAA,EAAU;AAGlD,IAAA,IAAI,OAAA,CAAQ,SAAS,aAAA,EAAe;AAClC,MAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,MAAA,IAAA,CAAK,KAAA,GAAQ,SAAS,IAAA,IAAQ,IAAA;AAC9B,MAAA,IAAA,CAAK,MAAA,GAAS,SAAS,KAAA,IAAS,OAAA;AAChC,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAEhB,MAAA,IAAI,KAAK,YAAA,EAAc;AACrB,QAAA,IAAA,CAAK,YAAA,CAAa,KAAK,KAAK,CAAA;AAC5B,QAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AAAA,MACtB;AAAA,IACF;AAGA,IAAA,IAAI,OAAA,CAAQ,SAAS,cAAA,EAAgB;AACnC,MAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,MAAA,IAAA,CAAK,MAAA,GAAS,SAAS,KAAA,IAAS,OAAA;AAGhC,MAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACnC,QAAA,QAAA,CAAS,eAAA,CAAgB,YAAA,CAAa,YAAA,EAAc,IAAA,CAAK,MAAM,CAAA;AAAA,MACjE;AAAA,IACF;AAGA,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA,CAAS,IAAI,OAAA,CAAQ,IAAI,KAAK,EAAC;AACrD,IAAA,QAAA,CAAS,QAAQ,CAAC,OAAA,KAAY,OAAA,CAAQ,OAAA,CAAQ,OAAO,CAAC,CAAA;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,EAAA,CAAgB,aAAqB,OAAA,EAAwC;AAC3E,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,WAAW,KAAK,EAAC;AACpD,IAAA,QAAA,CAAS,KAAK,OAAyB,CAAA;AACvC,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,WAAA,EAAa,QAAQ,CAAA;AAGvC,IAAA,OAAO,MAAM;AACX,MAAA,MAAM,UAAU,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,WAAW,KAAK,EAAC;AACnD,MAAA,IAAA,CAAK,QAAA,CAAS,GAAA;AAAA,QACZ,WAAA;AAAA,QACA,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,MAAM,OAAO;AAAA,OACrC;AAAA,IACF,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAA,EAA8B;AACzC,IAAA,IAAI,IAAA,CAAK,WAAA,IAAe,OAAO,MAAA,KAAW,WAAA,EAAa;AACrD,MAAA,MAAA,CAAO,MAAA,CAAO,WAAA,CAAY,OAAA,EAAS,GAAG,CAAA;AAAA,IACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,cAAA,EAA+B;AACtC,IAAA,IAAA,CAAK,YAAA,CAAa;AAAA,MAChB,IAAA,EAAM,WAAA;AAAA,MACN,OAAA,EAAS,EAAE,KAAA,EAAO,cAAA;AAAe,KAClC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAA,CACE,OAAA,EACA,IAAA,GAAqC,MAAA,EAC/B;AACN,IAAA,IAAA,CAAK,YAAA,CAAa;AAAA,MAChB,IAAA,EAAM,mBAAA;AAAA,MACN,OAAA,EAAS,EAAE,OAAA,EAAS,IAAA;AAAK,KAC1B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,IAAA,EAAoB;AAC3B,IAAA,IAAA,CAAK,YAAA,CAAa;AAAA,MAChB,IAAA,EAAM,UAAA;AAAA,MACN,OAAA,EAAS,EAAE,IAAA;AAAK,KACjB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAgB;AACd,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,MAAA,CAAO,oBAAoB,SAAA,EAAW,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,IACrE;AACA,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,EACtB;AACF;AAGA,IAAI,cAAA,GAAsC,IAAA;AAK1C,IAAM,UAAA,GAA4B;AAAA,EAChC,UAAA,EAAY,KAAA;AAAA,EACZ,OAAA,EAAS,IAAA;AAAA,EACT,IAAA,EAAM,IAAA;AAAA,EACN,KAAA,EAAO,OAAA;AAAA,EACP,YAAA,EAAc,MAAM,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA;AAAA,EACxC,EAAA,EAAI,MAAM,MAAM;AAAA,EAAC,CAAA;AAAA,EACjB,cAAc,MAAM;AAAA,EAAC,CAAA;AAAA,EACrB,UAAU,MAAM;AAAA,EAAC,CAAA;AAAA,EACjB,kBAAkB,MAAM;AAAA,EAAC,CAAA;AAAA,EACzB,UAAU,MAAM;AAAA,EAAC,CAAA;AAAA,EACjB,SAAS,MAAM;AAAA,EAAC;AAClB,CAAA;AAMO,SAAS,SAAA,GAA2B;AACzC,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEjC,IAAA,OAAO,UAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,IAAA,cAAA,GAAiB,IAAI,YAAA,EAAa;AAAA,EACpC;AACA,EAAA,OAAO,cAAA;AACT;AAMO,SAAS,kBAAA,GAA8B;AAC5C,EAAA,OAAO,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,SAAS,MAAA,CAAO,GAAA;AACjE;;;ACnPO,IAAM,eAAN,MAAmB;AAAA,EAMxB,WAAA,CAAY,MAAA,GAAuB,EAAC,EAAG;AACrC,IAAA,IAAA,CAAK,MAAA,GAAS,OAAO,MAAA,IAAU,EAAA;AAC/B,IAAA,IAAA,CAAK,MAAA,GAAS,OAAO,MAAA,IAAU,EAAA;AAC/B,IAAA,IAAA,CAAK,MAAA,GAAS,OAAO,MAAA,IAAU,EAAA;AAC/B,IAAA,IAAA,CAAK,KAAA,GAAQ,OAAO,KAAA,IAAS,KAAA;AAAA,EAC/B;AAAA;AAAA,EAGA,IAAI,YAAA,GAAwB;AAC1B,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,MAAM,CAAA;AAAA,EAC3C;AAAA,EAEQ,OAAO,IAAA,EAAuB;AACpC,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,GAAA,CAAI,gBAAA,EAAkB,GAAG,IAAI,CAAA;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,MAAc,OAAA,CACZ,MAAA,EACA,IAAA,EACA,IAAA,EACY;AACZ,IAAA,IAAI,CAAC,KAAK,YAAA,EAAc;AACtB,MAAA,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAAA,IACzE;AAEA,IAAA,MAAM,GAAA,GAAM,GAAG,IAAA,CAAK,MAAA,CAAO,QAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA;AACpD,IAAA,IAAA,CAAK,IAAI,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,GAAG,IAAI,IAAI,CAAA;AAEjC,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MAChC,MAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,aAAa,IAAA,CAAK,MAAA;AAAA,QAClB,oBAAoB,IAAA,CAAK;AAAA,OAC3B;AAAA,MACA,IAAA,EAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GAAI;AAAA,KACrC,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAK;AACtC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,SAAS,MAAM,CAAA,GAAA,EAAM,SAAS,CAAA,CAAE,CAAA;AAAA,IACvE;AAEA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KACJ,GAAA,EACyC;AACzC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,sBAAA,EAAwB;AAAA,MAClD,aAAa,GAAA,CAAI,EAAA;AAAA,MACjB,eAAe,GAAA,CAAI,IAAA;AAAA,MACnB,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,cAAc,GAAA,CAAI,WAAA;AAAA,MAClB,YAAA,EAAc,IAAI,KAAA,IAAS,QAAA;AAAA,MAC3B,gBAAgB,GAAA,CAAI,OAAA;AAAA,MACpB,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,CACJ,QAAA,EACA,OAAA,GAAiD,EAAC,EACtB;AAC5B,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAYzB,QAAQ,kBAAA,EAAoB;AAAA,MAC7B,KAAA,EAAO,QAAA;AAAA,MACP,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,iBAAiB,OAAA,CAAQ,aAAA;AAAA,MACzB,WAAA,EAAa,QAAQ,UAAA,IAAc,EAAA;AAAA,MACnC,YAAY,OAAA,CAAQ;AAAA,KACrB,CAAA;AAED,IAAA,OAAO;AAAA,MACL,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,SAAS,QAAA,CAAS,OAAA;AAAA,MAClB,OAAO,QAAA,CAAS;AAAA,KAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eAAe,SAAA,EAA+C;AAClE,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,OAAA;AAAA,QAChB,KAAA;AAAA,QACA,CAAA,mBAAA,EAAsB,kBAAA,CAAmB,SAAS,CAAC,CAAA;AAAA,OACrD;AAAA,IACF,SAAS,KAAA,EAAO;AAEd,MAAA,IAAI,iBAAiB,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3D,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cAAc,MAAA,EAQ2B;AAC7C,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,oCAAA,EAAsC;AAAA,MAChE,sBAAsB,MAAA,CAAO,kBAAA;AAAA,MAC7B,iBAAiB,MAAA,CAAO,aAAA;AAAA,MACxB,mBAAmB,MAAA,CAAO,eAAA;AAAA,MAC1B,eAAe,MAAA,CAAO,YAAA;AAAA,MACtB,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,cAAc,MAAA,CAAO,WAAA;AAAA,MACrB,UAAU,MAAA,CAAO;AAAA,KAClB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YACJ,YAAA,EACuF;AACvF,IAAA,MAAM,SAAS,YAAA,GACX,CAAA,eAAA,EAAkB,kBAAA,CAAmB,YAAY,CAAC,CAAA,CAAA,GAClD,EAAA;AACJ,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,CAAA,6BAAA,EAAgC,MAAM,CAAA,CAAE,CAAA;AAAA,EACrE;AACF;AAKO,SAAS,mBAAmB,MAAA,EAAoC;AACrE,EAAA,OAAO,IAAI,aAAa,MAAM,CAAA;AAChC;ACnLA,IAAM,aAAA,GAAgB,cAAyC,IAAI,CAAA;AAoC5D,SAAS,cAAA,CAAe;AAAA,EAC7B,QAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA,GAAQ;AACV,CAAA,EAAwB;AAEtB,EAAA,MAAM,CAAC,MAAM,CAAA,GAAI,QAAA,CAAwB,MAAM,WAAW,CAAA;AAG1D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA,CAAS,OAAO,OAAO,CAAA;AACrD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,QAAA,CAA4B,OAAO,IAAI,CAAA;AAC/D,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAA,CAA2B,OAAO,KAAK,CAAA;AAGjE,EAAA,MAAM,MAAA,GAAS,OAAA;AAAA,IACb,MACE,IAAI,YAAA,CAAa;AAAA,MACf,MAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,IACH,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,KAAK;AAAA,GAChC;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAA,CAAO,YAAA,EAAa,CAAE,IAAA,CAAK,CAAC,UAAA,KAAe;AACzC,MAAA,OAAA,CAAQ,UAAU,CAAA;AAClB,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,QAAA,CAAS,OAAO,KAAK,CAAA;AAAA,IACvB,CAAC,CAAA;AAGD,IAAA,MAAM,cAAc,MAAA,CAAO,EAAA;AAAA,MACzB,cAAA;AAAA,MACA,CAAC,OAAA,KAAY;AACX,QAAA,IAAI,SAAS,KAAA,EAAO;AAClB,UAAA,QAAA,CAAS,QAAQ,KAAK,CAAA;AAAA,QACxB;AAAA,MACF;AAAA,KACF;AAEA,IAAA,OAAO,WAAA;AAAA,EACT,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAGX,EAAA,MAAM,IAAA,GAAO,WAAA;AAAA,IACX,OAAO,GAAA,KAA6D;AAClE,MAAA,IAAI,CAAC,OAAO,YAAA,EAAc;AACxB,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,OAAA,CAAQ,KAAK,oDAAoD,CAAA;AAAA,QACnE;AACA,QAAA;AAAA,MACF;AACA,MAAA,MAAM,MAAA,CAAO,KAAK,GAAG,CAAA;AAAA,IACvB,CAAA;AAAA,IACA,CAAC,QAAQ,KAAK;AAAA,GAChB;AAGA,EAAA,MAAM,KAAA,GAAQ,WAAA;AAAA,IACZ,OACE,UACA,OAAA,KAC+B;AAC/B,MAAA,IAAI,CAAC,OAAO,YAAA,EAAc;AACxB,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,OAAA,CAAQ,KAAK,qDAAqD,CAAA;AAAA,QACpE;AACA,QAAA,OAAO;AAAA,UACL,MAAA,EAAQ,EAAA;AAAA,UACR,SAAS,EAAC;AAAA,UACV,KAAA,EAAO;AAAA,SACT;AAAA,MACF;AACA,MAAA,OAAO,MAAA,CAAO,MAAM,QAAA,EAAU;AAAA,QAC5B,GAAG,OAAA;AAAA,QACH,WAAW,IAAA,EAAM;AAAA,OAClB,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,IAAA,EAAM,KAAK;AAAA,GACtB;AAGA,EAAA,MAAM,QAAA,GAAW,WAAA;AAAA,IACf,CAAC,cAAA,KAA4B;AAC3B,MAAA,MAAA,CAAO,SAAS,cAAc,CAAA;AAAA,IAChC,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAGA,EAAA,MAAM,gBAAA,GAAmB,WAAA;AAAA,IACvB,CAAC,SAAiB,IAAA,KAAwC;AACxD,MAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,IAAI,CAAA;AAAA,IACvC,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAGA,EAAA,MAAM,KAAA,GAA4B,OAAA;AAAA,IAChC,OAAO;AAAA,MACL,IAAA;AAAA,MACA,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,OAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA,CAAC,MAAM,MAAA,CAAO,UAAA,EAAY,SAAS,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,QAAA,EAAU,gBAAgB;AAAA,GACnF;AAEA,EAAA,uBACE,GAAA,CAAC,aAAA,CAAc,QAAA,EAAd,EAAuB,OAAe,QAAA,EAAS,CAAA;AAEpD;AA2BO,SAAS,SAAA,GAAgC;AAC9C,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AAExC,EAAA,IAAI,CAAC,OAAA,EAAS;AAEZ,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAA;AAAA,MACN,UAAA,EAAY,KAAA;AAAA,MACZ,OAAA,EAAS,IAAA;AAAA,MACT,KAAA,EAAO,OAAA;AAAA,MACP,MAAM,YAAY;AAChB,QAAA,OAAA,CAAQ,KAAK,0CAA0C,CAAA;AAAA,MACzD,CAAA;AAAA,MACA,KAAA,EAAO,OAAO,CAAA,MAAO;AAAA,QACnB,MAAA,EAAQ,EAAA;AAAA,QACR,SAAS,EAAC;AAAA,QACV,KAAA,EAAO;AAAA,OACT,CAAA;AAAA,MACA,UAAU,MAAM;AAAA,MAAC,CAAA;AAAA,MACjB,kBAAkB,MAAM;AAAA,MAAC;AAAA,KAC3B;AAAA,EACF;AAEA,EAAA,OAAO,OAAA;AACT;AAMO,SAAS,aAAA,GAAyB;AACvC,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,SAAS,UAAA,IAAc,KAAA;AAChC;AAMO,SAAS,aAAA,GAAmC;AACjD,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,SAAS,IAAA,IAAQ,IAAA;AAC1B;AAKO,SAAS,cAAA,GAAmC;AACjD,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,SAAS,KAAA,IAAS,OAAA;AAC3B","file":"index.mjs","sourcesContent":["/**\n * CortexBridge - PostMessage communication for iframe embedding.\n *\n * Handles bidirectional communication between tool (iframe) and\n * Cortex shell (parent window).\n */\n\nimport type {\n CortexUser,\n CortexMessage,\n CortexInitPayload,\n CortexThemePayload,\n} from './types';\n\ntype MessageHandler<T = unknown> = (payload: T) => void;\n\n/**\n * Public interface for CortexBridge.\n */\nexport interface ICortexBridge {\n readonly isEmbedded: boolean;\n readonly isReady: boolean;\n readonly user: CortexUser | null;\n readonly theme: 'light' | 'dark';\n waitForReady(): Promise<CortexUser | null>;\n on<T = unknown>(messageType: string, handler: MessageHandler<T>): () => void;\n sendToParent(message: CortexMessage): void;\n openChat(prefilledQuery?: string): void;\n showNotification(message: string, type?: 'success' | 'error' | 'info'): void;\n navigate(path: string): void;\n destroy(): void;\n}\n\n/**\n * Bridge for postMessage communication with Cortex shell.\n *\n * @example\n * ```typescript\n * const bridge = new CortexBridge();\n *\n * // Wait for initialization\n * const user = await bridge.waitForReady();\n *\n * // Send messages to Cortex\n * bridge.openChat('What were the action items?');\n * bridge.showNotification('Document saved', 'success');\n * ```\n */\nexport class CortexBridge implements ICortexBridge {\n private handlers: Map<string, MessageHandler[]> = new Map();\n private parentOrigin: string | null = null;\n private _isEmbedded: boolean;\n private _isReady: boolean = false;\n private _user: CortexUser | null = null;\n private _theme: 'light' | 'dark' = 'light';\n private readyPromise: Promise<CortexUser | null>;\n private readyResolve: ((user: CortexUser | null) => void) | null = null;\n\n constructor() {\n // Detect if running in iframe\n this._isEmbedded =\n typeof window !== 'undefined' && window.self !== window.top;\n\n // Create ready promise\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n\n if (this._isEmbedded && typeof window !== 'undefined') {\n // Set up message listener\n window.addEventListener('message', this.handleMessage.bind(this));\n\n // Notify parent we're ready\n this.sendToParent({ type: 'TOOL_READY' });\n\n // Timeout if no response\n setTimeout(() => {\n if (this.readyResolve) {\n this._isReady = true;\n this.readyResolve(null);\n this.readyResolve = null;\n }\n }, 5000);\n } else {\n // Not embedded - resolve immediately\n this._isReady = true;\n if (this.readyResolve) {\n this.readyResolve(null);\n this.readyResolve = null;\n }\n }\n }\n\n /** Whether app is embedded in Cortex shell */\n get isEmbedded(): boolean {\n return this._isEmbedded;\n }\n\n /** Whether bridge is initialized */\n get isReady(): boolean {\n return this._isReady;\n }\n\n /** Current user from Cortex (null if standalone) */\n get user(): CortexUser | null {\n return this._user;\n }\n\n /** Current theme from Cortex */\n get theme(): 'light' | 'dark' {\n return this._theme;\n }\n\n /**\n * Wait for Cortex initialization.\n * Resolves with user if embedded, null if standalone.\n */\n waitForReady(): Promise<CortexUser | null> {\n return this.readyPromise;\n }\n\n private handleMessage(event: MessageEvent) {\n // Validate origin (first message from parent sets allowed origin)\n if (!this.parentOrigin) {\n this.parentOrigin = event.origin;\n } else if (event.origin !== this.parentOrigin) {\n console.warn('CortexBridge: Rejected message from unexpected origin:', event.origin);\n return;\n }\n\n const message = event.data as CortexMessage;\n if (!message || typeof message.type !== 'string') return;\n\n // Handle CORTEX_INIT message\n if (message.type === 'CORTEX_INIT') {\n const payload = message.payload as CortexInitPayload;\n this._user = payload?.user ?? null;\n this._theme = payload?.theme ?? 'light';\n this._isReady = true;\n\n if (this.readyResolve) {\n this.readyResolve(this._user);\n this.readyResolve = null;\n }\n }\n\n // Handle CORTEX_THEME message\n if (message.type === 'CORTEX_THEME') {\n const payload = message.payload as CortexThemePayload;\n this._theme = payload?.theme ?? 'light';\n\n // Apply theme to document\n if (typeof document !== 'undefined') {\n document.documentElement.setAttribute('data-theme', this._theme);\n }\n }\n\n // Call registered handlers\n const handlers = this.handlers.get(message.type) || [];\n handlers.forEach((handler) => handler(message.payload));\n }\n\n /**\n * Register a handler for a message type.\n * Returns unsubscribe function.\n */\n on<T = unknown>(messageType: string, handler: MessageHandler<T>): () => void {\n const handlers = this.handlers.get(messageType) || [];\n handlers.push(handler as MessageHandler);\n this.handlers.set(messageType, handlers);\n\n // Return unsubscribe function\n return () => {\n const current = this.handlers.get(messageType) || [];\n this.handlers.set(\n messageType,\n current.filter((h) => h !== handler)\n );\n };\n }\n\n /**\n * Send a message to parent window (Cortex shell).\n */\n sendToParent(message: CortexMessage): void {\n if (this._isEmbedded && typeof window !== 'undefined') {\n window.parent.postMessage(message, '*');\n }\n }\n\n /**\n * Open Cortex chat, optionally with a prefilled query.\n */\n openChat(prefilledQuery?: string): void {\n this.sendToParent({\n type: 'OPEN_CHAT',\n payload: { query: prefilledQuery },\n });\n }\n\n /**\n * Show a notification in Cortex shell.\n */\n showNotification(\n message: string,\n type: 'success' | 'error' | 'info' = 'info'\n ): void {\n this.sendToParent({\n type: 'SHOW_NOTIFICATION',\n payload: { message, type },\n });\n }\n\n /**\n * Navigate to a path within Cortex.\n */\n navigate(path: string): void {\n this.sendToParent({\n type: 'NAVIGATE',\n payload: { path },\n });\n }\n\n /**\n * Cleanup - remove message listener.\n */\n destroy(): void {\n if (typeof window !== 'undefined') {\n window.removeEventListener('message', this.handleMessage.bind(this));\n }\n this.handlers.clear();\n }\n}\n\n// Singleton instance\nlet bridgeInstance: CortexBridge | null = null;\n\n/**\n * Noop bridge for SSR environments.\n */\nconst noopBridge: ICortexBridge = {\n isEmbedded: false,\n isReady: true,\n user: null,\n theme: 'light',\n waitForReady: () => Promise.resolve(null),\n on: () => () => {},\n sendToParent: () => {},\n openChat: () => {},\n showNotification: () => {},\n navigate: () => {},\n destroy: () => {},\n};\n\n/**\n * Get the shared CortexBridge instance.\n * Creates one if it doesn't exist.\n */\nexport function getBridge(): ICortexBridge {\n if (typeof window === 'undefined') {\n // SSR - return a mock bridge\n return noopBridge;\n }\n\n if (!bridgeInstance) {\n bridgeInstance = new CortexBridge();\n }\n return bridgeInstance;\n}\n\n/**\n * Check if currently embedded in Cortex shell.\n * Safe to call during SSR.\n */\nexport function isEmbeddedInCortex(): boolean {\n return typeof window !== 'undefined' && window.self !== window.top;\n}\n","/**\n * CortexClient - HTTP client for Cortex API.\n *\n * For direct API calls without React context.\n */\n\nimport type {\n CortexDocument,\n CortexQueryResult,\n CortexUser,\n CortexConfig,\n QueryOptions,\n CortexSource,\n} from './types';\n\n/**\n * HTTP client for Cortex Platform APIs.\n *\n * @example\n * ```typescript\n * const client = new CortexClient({\n * apiUrl: 'https://api.cortex.ai',\n * apiKey: 'your-api-key',\n * toolId: 'your-tool',\n * });\n *\n * await client.push({\n * id: 'doc_123',\n * type: 'meeting_transcript',\n * content: 'Full transcript...',\n * });\n * ```\n */\nexport class CortexClient {\n private apiUrl: string;\n private apiKey: string;\n private toolId: string;\n private debug: boolean;\n\n constructor(config: CortexConfig = {}) {\n this.apiUrl = config.apiUrl || '';\n this.apiKey = config.apiKey || '';\n this.toolId = config.toolId || '';\n this.debug = config.debug || false;\n }\n\n /** Whether client is configured */\n get isConfigured(): boolean {\n return Boolean(this.apiUrl && this.apiKey);\n }\n\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.log('[CortexClient]', ...args);\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n if (!this.isConfigured) {\n throw new Error('CortexClient not configured: missing apiUrl or apiKey');\n }\n\n const url = `${this.apiUrl.replace(/\\/$/, '')}${path}`;\n this.log(`${method} ${url}`, body);\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n 'X-Cortex-Tool-ID': this.toolId,\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Cortex API error (${response.status}): ${errorText}`);\n }\n\n return response.json();\n }\n\n /**\n * Push a document to Cortex Knowledge Graph.\n */\n async push(\n doc: Omit<CortexDocument, 'externalId'> & { id: string }\n ): Promise<{ id: string; status: string }> {\n return this.request('POST', '/api/tools/documents', {\n external_id: doc.id,\n document_type: doc.type,\n content: doc.content,\n name: doc.name,\n external_url: doc.externalUrl,\n access_scope: doc.scope || 'global',\n scope_team_ids: doc.teamIds,\n metadata: doc.metadata,\n });\n }\n\n /**\n * Query Cortex Knowledge Graph.\n */\n async query(\n question: string,\n options: QueryOptions & { userEmail?: string } = {}\n ): Promise<CortexQueryResult> {\n const response = await this.request<{\n answer: string;\n sources: Array<{\n id: string;\n type: string;\n name: string;\n excerpt: string;\n score?: number;\n url?: string;\n metadata?: Record<string, unknown>;\n }>;\n query: string;\n }>('POST', '/api/tools/query', {\n query: question,\n filters: options.filters,\n time_range_days: options.timeRangeDays,\n max_results: options.maxResults || 10,\n user_email: options.userEmail,\n });\n\n return {\n answer: response.answer,\n sources: response.sources as CortexSource[],\n query: response.query,\n };\n }\n\n /**\n * Get user context from Cortex.\n * Calls GET /api/tools/context/{userEmail}\n */\n async getUserContext(userEmail: string): Promise<CortexUser | null> {\n try {\n return await this.request<CortexUser>(\n 'GET',\n `/api/tools/context/${encodeURIComponent(userEmail)}`\n );\n } catch (error) {\n // Return null if user not found\n if (error instanceof Error && error.message.includes('404')) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Share a document with another user.\n * Calls POST /api/tools/share-document-for-user\n *\n * Creates a share record so the document appears in\n * the recipient's \"Shared with Me\" at /personal/shared.\n */\n async shareDocument(params: {\n documentExternalId: string;\n sharedByEmail: string;\n sharedWithEmail: string;\n documentName?: string;\n content?: string;\n externalUrl?: string;\n metadata?: Record<string, unknown>;\n }): Promise<{ success: boolean; id?: string }> {\n return this.request('POST', '/api/tools/share-document-for-user', {\n document_external_id: params.documentExternalId,\n shared_by_email: params.sharedByEmail,\n shared_with_email: params.sharedWithEmail,\n document_name: params.documentName,\n content: params.content,\n external_url: params.externalUrl,\n metadata: params.metadata,\n });\n }\n\n /**\n * Get list of users in the tool's organization.\n * Calls GET /api/tools/org-users-for-tool\n */\n async getOrgUsers(\n excludeEmail?: string\n ): Promise<Array<{ id: string; email: string; full_name: string; avatar_url?: string }>> {\n const params = excludeEmail\n ? `?exclude_email=${encodeURIComponent(excludeEmail)}`\n : '';\n return this.request('GET', `/api/tools/org-users-for-tool${params}`);\n }\n}\n\n/**\n * Create a configured CortexClient instance.\n */\nexport function createCortexClient(config: CortexConfig): CortexClient {\n return new CortexClient(config);\n}\n","/**\n * CortexProvider - React context for Cortex integration.\n */\n\nimport {\n createContext,\n useContext,\n useEffect,\n useState,\n useCallback,\n useMemo,\n type ReactNode,\n} from 'react';\n\nimport { getBridge, type ICortexBridge } from './bridge';\nimport { CortexClient } from './client';\nimport type {\n CortexUser,\n CortexDocument,\n CortexQueryResult,\n CortexContextValue,\n QueryOptions,\n} from './types';\n\n// Create context with null default\nconst CortexContext = createContext<CortexContextValue | null>(null);\n\n/**\n * Props for CortexProvider component.\n */\nexport interface CortexProviderProps {\n children: ReactNode;\n /** Cortex gateway URL (for API calls) */\n apiUrl?: string;\n /** Tool's API key */\n apiKey?: string;\n /** Tool identifier */\n toolId?: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Provider component for Cortex integration.\n *\n * Wrap your app with this provider to enable Cortex features.\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <CortexProvider\n * apiUrl={process.env.REACT_APP_CORTEX_API_URL}\n * apiKey={process.env.REACT_APP_CORTEX_API_KEY}\n * >\n * <YourApp />\n * </CortexProvider>\n * );\n * }\n * ```\n */\nexport function CortexProvider({\n children,\n apiUrl,\n apiKey,\n toolId,\n debug = false,\n}: CortexProviderProps) {\n // Get shared bridge instance\n const [bridge] = useState<ICortexBridge>(() => getBridge());\n\n // State from bridge\n const [isReady, setIsReady] = useState(bridge.isReady);\n const [user, setUser] = useState<CortexUser | null>(bridge.user);\n const [theme, setTheme] = useState<'light' | 'dark'>(bridge.theme);\n\n // Create API client\n const client = useMemo(\n () =>\n new CortexClient({\n apiUrl,\n apiKey,\n toolId,\n debug,\n }),\n [apiUrl, apiKey, toolId, debug]\n );\n\n // Wait for bridge initialization\n useEffect(() => {\n bridge.waitForReady().then((cortexUser) => {\n setUser(cortexUser);\n setIsReady(true);\n setTheme(bridge.theme);\n });\n\n // Listen for theme changes\n const unsubscribe = bridge.on<{ theme: 'light' | 'dark' }>(\n 'CORTEX_THEME',\n (payload) => {\n if (payload?.theme) {\n setTheme(payload.theme);\n }\n }\n );\n\n return unsubscribe;\n }, [bridge]);\n\n // Push document to Cortex\n const push = useCallback(\n async (doc: Omit<CortexDocument, 'externalId'> & { id: string }) => {\n if (!client.isConfigured) {\n if (debug) {\n console.warn('CortexProvider: push called but API not configured');\n }\n return;\n }\n await client.push(doc);\n },\n [client, debug]\n );\n\n // Query Cortex\n const query = useCallback(\n async (\n question: string,\n options?: QueryOptions\n ): Promise<CortexQueryResult> => {\n if (!client.isConfigured) {\n if (debug) {\n console.warn('CortexProvider: query called but API not configured');\n }\n return {\n answer: '',\n sources: [],\n query: question,\n };\n }\n return client.query(question, {\n ...options,\n userEmail: user?.email,\n });\n },\n [client, user, debug]\n );\n\n // Open Cortex chat\n const openChat = useCallback(\n (prefilledQuery?: string) => {\n bridge.openChat(prefilledQuery);\n },\n [bridge]\n );\n\n // Show notification\n const showNotification = useCallback(\n (message: string, type?: 'success' | 'error' | 'info') => {\n bridge.showNotification(message, type);\n },\n [bridge]\n );\n\n // Build context value\n const value: CortexContextValue = useMemo(\n () => ({\n user,\n isEmbedded: bridge.isEmbedded,\n isReady,\n theme,\n push,\n query,\n openChat,\n showNotification,\n }),\n [user, bridge.isEmbedded, isReady, theme, push, query, openChat, showNotification]\n );\n\n return (\n <CortexContext.Provider value={value}>{children}</CortexContext.Provider>\n );\n}\n\n/**\n * Hook to access Cortex context.\n *\n * Returns a no-op implementation if used outside CortexProvider,\n * making it safe to use in components that may render both\n * inside and outside the provider.\n *\n * @example\n * ```tsx\n * function MeetingCard({ meeting }) {\n * const { isEmbedded, openChat } = useCortex();\n *\n * return (\n * <div>\n * <h3>{meeting.title}</h3>\n * {isEmbedded && (\n * <button onClick={() => openChat(`Tell me about ${meeting.title}`)}>\n * Ask Cortex\n * </button>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useCortex(): CortexContextValue {\n const context = useContext(CortexContext);\n\n if (!context) {\n // Return no-op implementation for use outside provider\n return {\n user: null,\n isEmbedded: false,\n isReady: true,\n theme: 'light',\n push: async () => {\n console.warn('useCortex: called outside CortexProvider');\n },\n query: async (q) => ({\n answer: '',\n sources: [],\n query: q,\n }),\n openChat: () => {},\n showNotification: () => {},\n };\n }\n\n return context;\n}\n\n/**\n * Hook to check if currently embedded in Cortex.\n * More efficient than useCortex() if you only need the embedded status.\n */\nexport function useIsEmbedded(): boolean {\n const context = useContext(CortexContext);\n return context?.isEmbedded ?? false;\n}\n\n/**\n * Hook to get current Cortex user.\n * Returns null if not embedded or not authenticated.\n */\nexport function useCortexUser(): CortexUser | null {\n const context = useContext(CortexContext);\n return context?.user ?? null;\n}\n\n/**\n * Hook to get current theme from Cortex.\n */\nexport function useCortexTheme(): 'light' | 'dark' {\n const context = useContext(CortexContext);\n return context?.theme ?? 'light';\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "lyzr-cortex-sdk",
3
+ "version": "0.1.2",
4
+ "description": "SDK for building tools that integrate with Cortex Platform",
5
+ "author": "Cortex Lyzr AI",
6
+ "email":"krish@lyzr.ai",
7
+ "license": "MIT",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "dev": "tsup --watch",
24
+ "lint": "eslint src --ext .ts,.tsx",
25
+ "typecheck": "tsc --noEmit",
26
+ "test": "vitest",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "peerDependencies": {
30
+ "react": ">=18.0.0"
31
+ },
32
+ "peerDependenciesMeta": {
33
+ "react": {
34
+ "optional": true
35
+ }
36
+ },
37
+ "devDependencies": {
38
+ "@types/react": "^18.2.0",
39
+ "react": "^18.2.0",
40
+ "tsup": "^8.0.0",
41
+ "typescript": "^5.3.0",
42
+ "vitest": "^1.0.0"
43
+ },
44
+ "keywords": [
45
+ "cortex",
46
+ "sdk",
47
+ "tools",
48
+ "integration",
49
+ "rag",
50
+ "react",
51
+ "iframe"
52
+ ],
53
+ "repository": {
54
+ "type": "git"
55
+ },
56
+ "homepage": "https://cortex.lyzr.app/docs",
57
+ "bugs": {
58
+ }
59
+ }