@datalayer/core 0.0.16 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/lib/components/chat/ChatComponent.d.ts +4 -0
  2. package/lib/components/chat/ChatComponent.js +139 -0
  3. package/lib/components/chat/MessagePart.d.ts +11 -0
  4. package/lib/components/chat/MessagePart.js +23 -0
  5. package/lib/components/chat/display/DynamicToolPart.d.ts +6 -0
  6. package/lib/components/chat/display/DynamicToolPart.js +5 -0
  7. package/lib/components/chat/display/ReasoningPart.d.ts +6 -0
  8. package/lib/components/chat/display/ReasoningPart.js +54 -0
  9. package/lib/components/chat/display/TextPart.d.ts +9 -0
  10. package/lib/components/chat/display/TextPart.js +93 -0
  11. package/lib/components/chat/display/ToolPart.d.ts +6 -0
  12. package/lib/components/chat/display/ToolPart.js +144 -0
  13. package/lib/components/chat/display/index.d.ts +4 -0
  14. package/lib/components/chat/display/index.js +9 -0
  15. package/lib/components/chat/handler.d.ts +8 -0
  16. package/lib/components/chat/handler.js +39 -0
  17. package/lib/components/chat/index.d.ts +4 -0
  18. package/lib/components/chat/index.js +9 -0
  19. package/lib/components/index.d.ts +1 -1
  20. package/lib/components/index.js +1 -1
  21. package/lib/components/runtimes/RuntimeSimplePicker.d.ts +4 -0
  22. package/lib/components/runtimes/RuntimeSimplePicker.js +3 -3
  23. package/lib/examples/ChatExample.d.ts +8 -0
  24. package/lib/examples/ChatExample.js +51 -0
  25. package/lib/examples/example-selector.js +1 -0
  26. package/lib/hooks/useAIJupyterChat.d.ts +36 -0
  27. package/lib/hooks/useAIJupyterChat.js +49 -0
  28. package/lib/hooks/useCache.js +99 -44
  29. package/lib/hooks/useMobile.d.ts +1 -0
  30. package/lib/hooks/useMobile.js +22 -0
  31. package/lib/hooks/useUpload.js +29 -21
  32. package/lib/index.d.ts +1 -0
  33. package/lib/index.js +8 -4
  34. package/lib/stateful/index.d.ts +0 -1
  35. package/lib/stateful/index.js +0 -1
  36. package/lib/stateful/runtimes/actions.d.ts +1 -1
  37. package/lib/stateful/runtimes/actions.js +1 -1
  38. package/lib/theme/DatalayerTheme.d.ts +2 -2
  39. package/lib/theme/DatalayerTheme.js +4 -4
  40. package/lib/theme/DatalayerThemeProvider.js +2 -2
  41. package/lib/types.d.ts +5 -0
  42. package/lib/types.js +6 -0
  43. package/package.json +16 -2
  44. package/style/base.css +4 -0
@@ -35,7 +35,7 @@ var RuntimeDialogCause;
35
35
  * Runtime simple picker component.
36
36
  */
37
37
  export function RuntimeSimplePicker(props) {
38
- const { assignRuntime, sessionConnection } = props;
38
+ const { assignRuntime, sessionConnection, browserRuntimeAvailable = true, } = props;
39
39
  const { runtimeModels, multiServiceManager } = useRuntimesStore();
40
40
  const jupyterReactStore = useJupyterReactStore();
41
41
  const jupyterLabAdapter = jupyterReactStore.jupyterLabAdapter;
@@ -120,7 +120,7 @@ export function RuntimeSimplePicker(props) {
120
120
  sessionConnection === undefined, onSelect: () => {
121
121
  setRuntimeLocation(undefined);
122
122
  assignRuntime({ runtimeDesc: undefined });
123
- }, children: [_jsx(ActionList.LeadingVisual, { children: _jsx(EyeIcon, {}) }), "Viewer", _jsx(ActionList.Description, { variant: "block", children: "A simple Notebook Viewer without Runtime." })] }), _jsxs(ActionList.Item, { selected: runtimeLocation === 'browser', onSelect: () => {
123
+ }, children: [_jsx(ActionList.LeadingVisual, { children: _jsx(EyeIcon, {}) }), "Viewer", _jsx(ActionList.Description, { variant: "block", children: "A simple Notebook Viewer without Runtime." })] }), browserRuntimeAvailable && (_jsxs(ActionList.Item, { selected: runtimeLocation === 'browser', onSelect: () => {
124
124
  setRuntimeLocation('browser');
125
125
  assignRuntime({
126
126
  runtimeDesc: {
@@ -129,7 +129,7 @@ export function RuntimeSimplePicker(props) {
129
129
  language: 'python',
130
130
  },
131
131
  });
132
- }, children: [_jsx(ActionList.LeadingVisual, { children: _jsx(BrowserIcon, {}) }), "Browser Runtime", _jsx(ActionList.Description, { variant: "block", children: "A Browser Runtime based on Pyodide." })] })] }), runtimeModels.length > 0 && (_jsxs(ActionList.Group, { children: [_jsx(ActionList.GroupHeading, { children: "Cloud Runtimes" }), runtimeModels.map(kernelModel => {
132
+ }, children: [_jsx(ActionList.LeadingVisual, { children: _jsx(BrowserIcon, {}) }), "Browser Runtime", _jsx(ActionList.Description, { variant: "block", children: "A Browser Runtime based on Pyodide." })] }))] }), runtimeModels.length > 0 && (_jsxs(ActionList.Group, { children: [_jsx(ActionList.GroupHeading, { children: "Cloud Runtimes" }), runtimeModels.map(kernelModel => {
133
133
  return (_jsxs(ActionList.Item, { selected: sessionConnection?.kernel?.id === kernelModel.id, onSelect: () => {
134
134
  setRuntimeLocation('remote');
135
135
  assignRuntime({
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Chat Example Component
3
+ *
4
+ * Demonstrates the ChatComponent with all necessary providers:
5
+ * - QueryClientProvider for data fetching
6
+ */
7
+ declare const ChatExample: React.FC;
8
+ export default ChatExample;
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2024-2025 Datalayer, Inc.
4
+ *
5
+ * BSD 3-Clause License
6
+ */
7
+ import { Text } from '@primer/react';
8
+ import { Box } from '@datalayer/primer-addons';
9
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
10
+ import { ChatComponent } from '../components/chat/ChatComponent';
11
+ import { datalayerTheme, DatalayerThemeProvider } from '@/theme';
12
+ // Create a query client for React Query
13
+ const queryClient = new QueryClient({
14
+ defaultOptions: {
15
+ queries: {
16
+ staleTime: 1000 * 60 * 5, // 5 minutes
17
+ gcTime: 1000 * 60 * 10, // 10 minutes
18
+ retry: 1,
19
+ refetchOnWindowFocus: false,
20
+ },
21
+ },
22
+ });
23
+ /**
24
+ * Chat Example Component
25
+ *
26
+ * Demonstrates the ChatComponent with all necessary providers:
27
+ * - QueryClientProvider for data fetching
28
+ */
29
+ const ChatExample = () => {
30
+ return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(DatalayerThemeProvider, { theme: datalayerTheme, children: _jsxs(Box, { sx: {
31
+ display: 'flex',
32
+ flexDirection: 'column',
33
+ height: '100vh',
34
+ backgroundColor: 'canvas.default',
35
+ }, children: [_jsxs(Box, { as: "header", sx: {
36
+ borderBottom: '1px solid',
37
+ borderColor: 'border.default',
38
+ padding: 3,
39
+ }, children: [_jsx(Text, { sx: {
40
+ fontSize: 3,
41
+ fontWeight: 'bold',
42
+ display: 'block',
43
+ marginBottom: 1,
44
+ }, children: "Chat Example" }), _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "Interactive chat interface with AI assistance" })] }), _jsx(Box, { as: "main", sx: {
45
+ flex: 1,
46
+ overflow: 'hidden',
47
+ display: 'flex',
48
+ flexDirection: 'column',
49
+ }, children: _jsx(ChatComponent, {}) })] }) }) }));
50
+ };
51
+ export default ChatExample;
@@ -8,6 +8,7 @@
8
8
  */
9
9
  export const EXAMPLES = {
10
10
  CellExample: () => import('./CellExample'),
11
+ ChatExample: () => import('./ChatExample'),
11
12
  DatalayerNotebookExample: () => import('./DatalayerNotebookExample'),
12
13
  NotebookExample: () => import('./NotebookExample'),
13
14
  NotebookMutationsKernel: () => import('./NotebookMutationsKernel'),
@@ -0,0 +1,36 @@
1
+ export interface IUseAIJupyterChatOptions {
2
+ apiUrl?: string;
3
+ initialMessages?: unknown[];
4
+ }
5
+ /**
6
+ * Hook to manage chat state with JupyterLab backend.
7
+ * Adapts Vercel AI SDK's useChat for Datalayer AI context.
8
+ */
9
+ export declare function useAIJupyterChat(_options?: IUseAIJupyterChatOptions): {
10
+ messages: import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[];
11
+ sendMessage: (message?: (Omit<import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>, "id" | "role"> & {
12
+ id?: string | undefined;
13
+ role?: "user" | "system" | "assistant" | undefined;
14
+ } & {
15
+ text?: never;
16
+ files?: never;
17
+ messageId?: string;
18
+ }) | {
19
+ text: string;
20
+ files?: FileList | import("ai").FileUIPart[];
21
+ metadata?: unknown;
22
+ parts?: never;
23
+ messageId?: string;
24
+ } | {
25
+ files: FileList | import("ai").FileUIPart[];
26
+ metadata?: unknown;
27
+ parts?: never;
28
+ messageId?: string;
29
+ } | undefined, options?: import("ai").ChatRequestOptions) => Promise<void>;
30
+ status: import("ai").ChatStatus;
31
+ setMessages: (messages: import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[] | ((messages: import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[]) => import("ai").UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[])) => void;
32
+ regenerate: ({ messageId, ...options }?: {
33
+ messageId?: string;
34
+ } & import("ai").ChatRequestOptions) => Promise<void>;
35
+ clearChat: () => void;
36
+ };
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright (c) 2024-2025 Datalayer, Inc.
3
+ *
4
+ * BSD 3-Clause License
5
+ */
6
+ import { useCallback, useMemo } from 'react';
7
+ import { useChat } from '@ai-sdk/react';
8
+ import { DefaultChatTransport } from 'ai';
9
+ import { ServerConnection } from '@jupyterlab/services';
10
+ import { URLExt } from '@jupyterlab/coreutils';
11
+ /**
12
+ * Hook to manage chat state with JupyterLab backend.
13
+ * Adapts Vercel AI SDK's useChat for Datalayer AI context.
14
+ */
15
+ export function useAIJupyterChat(_options = {}) {
16
+ // Build the full API URL for the chat endpoint
17
+ const settings = ServerConnection.makeSettings();
18
+ const chatEndpoint = URLExt.join(settings.baseUrl, 'datalayer', 'chat');
19
+ const { messages, sendMessage, status, setMessages, regenerate } = useChat({
20
+ id: 'ai-jupyter-chat',
21
+ transport: new DefaultChatTransport({
22
+ api: chatEndpoint,
23
+ credentials: settings.token ? 'include' : 'omit',
24
+ headers: {
25
+ Authorization: `token ${settings.token || ''}`,
26
+ 'X-XSRFToken': settings.token || '',
27
+ },
28
+ fetch: async (input, init) => {
29
+ return fetch(input, {
30
+ ...init,
31
+ mode: 'cors',
32
+ credentials: settings.token ? 'include' : 'omit',
33
+ });
34
+ },
35
+ }),
36
+ });
37
+ // Clear chat history
38
+ const clearChat = useCallback(() => {
39
+ setMessages([]);
40
+ }, [setMessages]);
41
+ return useMemo(() => ({
42
+ messages,
43
+ sendMessage,
44
+ status,
45
+ setMessages,
46
+ regenerate,
47
+ clearChat,
48
+ }), [messages, sendMessage, status, setMessages, regenerate, clearChat]);
49
+ }
@@ -988,7 +988,6 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
988
988
  method: 'GET',
989
989
  });
990
990
  if (resp.success && resp.organizations) {
991
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
992
991
  const orgs = resp.organizations.map((org) => {
993
992
  const organization = toOrganization(org);
994
993
  // Pre-populate caches
@@ -1517,6 +1516,9 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
1517
1516
  return useQuery({
1518
1517
  queryKey: queryKeys.documents.bySpace(spaceId),
1519
1518
  queryFn: async () => {
1519
+ if (!spaceId) {
1520
+ return [];
1521
+ }
1520
1522
  const resp = await requestDatalayer({
1521
1523
  url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/items/types/document`,
1522
1524
  method: 'GET',
@@ -2104,7 +2106,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
2104
2106
  });
2105
2107
  };
2106
2108
  // ============================================================================
2107
- // BATCH 1: Core CRUD Operations - Refresh & Get Methods
2109
+ // Core CRUD Operations - Refresh & Get Methods
2108
2110
  // ============================================================================
2109
2111
  /**
2110
2112
  * Get single datasource by ID
@@ -2390,7 +2392,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
2390
2392
  });
2391
2393
  };
2392
2394
  // ============================================================================
2393
- // BATCH 2: Member Management & User Extensions
2395
+ // Member Management & User Extensions
2394
2396
  // ============================================================================
2395
2397
  /**
2396
2398
  * Refresh user data by ID (re-fetch from API)
@@ -2691,7 +2693,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
2691
2693
  });
2692
2694
  };
2693
2695
  // ============================================================================
2694
- // BATCH 3: Authentication, Roles, Schools, and Refresh Methods
2696
+ // Authentication, Roles, Schools, and Refresh Methods
2695
2697
  // ============================================================================
2696
2698
  /**
2697
2699
  * Change user password
@@ -2901,9 +2903,8 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
2901
2903
  return useMutation({
2902
2904
  mutationFn: async (organizationId) => {
2903
2905
  return requestDatalayer({
2904
- url: `${configuration.iamRunUrl}/api/iam/v1/teams`,
2906
+ url: `${configuration.iamRunUrl}/api/iam/v1/organizations/${organizationId}/teams`,
2905
2907
  method: 'GET',
2906
- body: { organizationId },
2907
2908
  });
2908
2909
  },
2909
2910
  onSuccess: (resp, organizationId) => {
@@ -2955,7 +2956,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
2955
2956
  return useMutation({
2956
2957
  mutationFn: async (organizationId) => {
2957
2958
  return requestDatalayer({
2958
- url: `${configuration.spacerRunUrl}/api/spacer/v1/organizations/${organizationId}/spaces`,
2959
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/organizations/${organizationId}`,
2959
2960
  method: 'GET',
2960
2961
  });
2961
2962
  },
@@ -3001,7 +3002,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3001
3002
  });
3002
3003
  };
3003
3004
  // ============================================================================
3004
- // BATCH 4: Courses, Space Items, and Advanced Features
3005
+ // Courses, Space Items, and Advanced Features
3005
3006
  // ============================================================================
3006
3007
  /**
3007
3008
  * Get course by ID
@@ -3220,24 +3221,30 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3220
3221
  },
3221
3222
  onSuccess: (resp, variables) => {
3222
3223
  if (resp.success) {
3224
+ // Transform raw API data to typed models
3225
+ const transformedUser = resp.user ? toUser(resp.user) : undefined;
3226
+ const transformedOrganization = resp.organization
3227
+ ? toOrganization(resp.organization)
3228
+ : undefined;
3229
+ const transformedSpace = resp.space ? toSpace(resp.space) : undefined;
3223
3230
  // Set data directly into cache instead of just invalidating
3224
- if (resp.user) {
3225
- queryClient.setQueryData(queryKeys.users.byHandle(variables.accountHandle), resp.user);
3231
+ if (transformedUser) {
3232
+ queryClient.setQueryData(queryKeys.users.byHandle(variables.accountHandle), transformedUser);
3226
3233
  queryClient.invalidateQueries({ queryKey: queryKeys.users.all() });
3227
3234
  }
3228
- if (resp.organization) {
3229
- queryClient.setQueryData(queryKeys.organizations.byHandle(variables.accountHandle), resp.organization);
3235
+ if (transformedOrganization) {
3236
+ queryClient.setQueryData(queryKeys.organizations.byHandle(variables.accountHandle), transformedOrganization);
3230
3237
  queryClient.invalidateQueries({
3231
3238
  queryKey: queryKeys.organizations.all(),
3232
3239
  });
3233
3240
  }
3234
- if (resp.space) {
3241
+ if (transformedSpace) {
3235
3242
  // Set both user and org space queries based on which type it is
3236
- if (resp.user && variables.spaceHandle) {
3237
- queryClient.setQueryData(queryKeys.spaces.byHandle(variables.spaceHandle), resp.space);
3243
+ if (transformedUser && variables.spaceHandle) {
3244
+ queryClient.setQueryData(queryKeys.spaces.byHandle(variables.spaceHandle), transformedSpace);
3238
3245
  }
3239
- if (resp.organization && variables.spaceHandle) {
3240
- queryClient.setQueryData(queryKeys.spaces.orgSpaceByHandle(resp.organization.id, variables.spaceHandle), resp.space);
3246
+ if (transformedOrganization && variables.spaceHandle) {
3247
+ queryClient.setQueryData(queryKeys.spaces.orgSpaceByHandle(transformedOrganization.id, variables.spaceHandle), transformedSpace);
3241
3248
  }
3242
3249
  queryClient.invalidateQueries({ queryKey: queryKeys.spaces.all() });
3243
3250
  }
@@ -3259,7 +3266,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3259
3266
  });
3260
3267
  };
3261
3268
  // ============================================================================
3262
- // BATCH 5: Cells, Datasets, Environments, and Lessons
3269
+ // Cells, Datasets, Environments, and Lessons
3263
3270
  // ============================================================================
3264
3271
  /**
3265
3272
  * Get cell by ID
@@ -3536,7 +3543,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3536
3543
  });
3537
3544
  };
3538
3545
  // ============================================================================
3539
- // BATCH 6: Exercises, Assignments, Invites, and Contacts
3546
+ // Exercises, Assignments, Invites, and Contacts
3540
3547
  // ============================================================================
3541
3548
  /**
3542
3549
  * Get exercise by ID
@@ -3768,7 +3775,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3768
3775
  });
3769
3776
  };
3770
3777
  // ============================================================================
3771
- // [BATCH 7] Assignment Student Operations
3778
+ // Assignment Student Operations
3772
3779
  // ============================================================================
3773
3780
  /**
3774
3781
  * Fetch assignment from student perspective with enrollment data
@@ -3851,7 +3858,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3851
3858
  });
3852
3859
  };
3853
3860
  // ============================================================================
3854
- // [BATCH 7] Exercise Grading
3861
+ // Exercise Grading
3855
3862
  // ============================================================================
3856
3863
  /**
3857
3864
  * Grade an exercise by assigning points to student code
@@ -3877,7 +3884,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3877
3884
  });
3878
3885
  };
3879
3886
  // ============================================================================
3880
- // [BATCH 7] Course Student & Course Items
3887
+ // Course Student & Course Items
3881
3888
  // ============================================================================
3882
3889
  /**
3883
3890
  * Get a student in a course
@@ -3946,7 +3953,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
3946
3953
  });
3947
3954
  };
3948
3955
  // ============================================================================
3949
- // [BATCH 7] Inbounds & Outbounds
3956
+ // Inbounds & Outbounds
3950
3957
  // ============================================================================
3951
3958
  /**
3952
3959
  * Get all inbound leads
@@ -4025,7 +4032,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4025
4032
  });
4026
4033
  };
4027
4034
  // ============================================================================
4028
- // [BATCH 8] Advanced Outbound Operations
4035
+ // Advanced Outbound Operations
4029
4036
  // ============================================================================
4030
4037
  /**
4031
4038
  * Try bulk emails (test mode) for outbound campaign
@@ -4103,7 +4110,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4103
4110
  });
4104
4111
  };
4105
4112
  // ============================================================================
4106
- // [BATCH 8] Outbound Subscriptions
4113
+ // Outbound Subscriptions
4107
4114
  // ============================================================================
4108
4115
  /**
4109
4116
  * Subscribe a user to outbound communications
@@ -4158,7 +4165,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4158
4165
  });
4159
4166
  };
4160
4167
  // ============================================================================
4161
- // [BATCH 8] MFA (Multi-Factor Authentication)
4168
+ // MFA (Multi-Factor Authentication)
4162
4169
  // ============================================================================
4163
4170
  /**
4164
4171
  * Enable MFA for current user
@@ -4209,7 +4216,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4209
4216
  });
4210
4217
  };
4211
4218
  // ============================================================================
4212
- // [BATCH 8] Checkout & Credits
4219
+ // Checkout & Credits
4213
4220
  // ============================================================================
4214
4221
  /**
4215
4222
  * Get Stripe pricing information
@@ -4264,7 +4271,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4264
4271
  });
4265
4272
  };
4266
4273
  // ============================================================================
4267
- // [BATCH 8] Support & Surveys
4274
+ // Support & Surveys
4268
4275
  // ============================================================================
4269
4276
  /**
4270
4277
  * Request platform support (first form)
@@ -4318,7 +4325,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4318
4325
  });
4319
4326
  };
4320
4327
  // ============================================================================
4321
- // [BATCH 9] Join & Registration
4328
+ // Join & Registration
4322
4329
  // ============================================================================
4323
4330
  /**
4324
4331
  * Request to join platform (standard registration)
@@ -4390,7 +4397,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4390
4397
  });
4391
4398
  };
4392
4399
  // ============================================================================
4393
- // [BATCH 9] Password Recovery
4400
+ // Password Recovery
4394
4401
  // ============================================================================
4395
4402
  /**
4396
4403
  * Create token for password change
@@ -4420,7 +4427,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4420
4427
  });
4421
4428
  };
4422
4429
  // ============================================================================
4423
- // [BATCH 9] OAuth2 Authentication
4430
+ // OAuth2 Authentication
4424
4431
  // ============================================================================
4425
4432
  /**
4426
4433
  * Get OAuth2 authorization URL
@@ -4456,7 +4463,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4456
4463
  });
4457
4464
  };
4458
4465
  // ============================================================================
4459
- // [BATCH 9] Contact Enrichment & Tagging
4466
+ // Contact Enrichment & Tagging
4460
4467
  // ============================================================================
4461
4468
  /**
4462
4469
  * Assign tag to contact
@@ -4571,7 +4578,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4571
4578
  });
4572
4579
  };
4573
4580
  // ============================================================================
4574
- // [BATCH 9] Contact-User Linking
4581
+ // Contact-User Linking
4575
4582
  // ============================================================================
4576
4583
  /**
4577
4584
  * Link user with contact
@@ -4618,7 +4625,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4618
4625
  });
4619
4626
  };
4620
4627
  // ============================================================================
4621
- // [BATCH 9] Credits Quota & Usage
4628
+ // Credits Quota & Usage
4622
4629
  // ============================================================================
4623
4630
  /**
4624
4631
  * Update user credits quota
@@ -4655,7 +4662,23 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4655
4662
  url: `${configuration.iamRunUrl}/api/iam/v1/usage/user`,
4656
4663
  method: 'GET',
4657
4664
  });
4658
- return resp.usages || [];
4665
+ // Transform snake_case API response to camelCase IUsage interface
4666
+ const usages = (resp.usages || []).map((u) => ({
4667
+ id: u.resource_uid,
4668
+ accountId: u.account_uid,
4669
+ type: u.resource_type,
4670
+ burningRate: u.burning_rate,
4671
+ credits: u.credits,
4672
+ creditsLimit: u.credits_limit,
4673
+ startDate: u.start_date ? new Date(u.start_date) : new Date(),
4674
+ updatedAt: u.updated_at ? new Date(u.updated_at) : new Date(),
4675
+ endDate: u.end_date ? new Date(u.end_date) : undefined,
4676
+ givenName: u.given_name || u.resource_given_name || '',
4677
+ resourceState: u.resource_state,
4678
+ resources: u.pod_resources,
4679
+ metadata: new Map(Object.entries(u.metadata || {})),
4680
+ }));
4681
+ return usages;
4659
4682
  },
4660
4683
  ...options,
4661
4684
  });
@@ -4671,7 +4694,23 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4671
4694
  url: `${configuration.iamRunUrl}/api/iam/v1/usage/users/${userId}`,
4672
4695
  method: 'GET',
4673
4696
  });
4674
- return resp.usages || [];
4697
+ // Transform snake_case API response to camelCase IUsage interface
4698
+ const usages = (resp.usages || []).map((u) => ({
4699
+ id: u.resource_uid,
4700
+ accountId: u.account_uid,
4701
+ type: u.resource_type,
4702
+ burningRate: u.burning_rate,
4703
+ credits: u.credits,
4704
+ creditsLimit: u.credits_limit,
4705
+ startDate: u.start_date ? new Date(u.start_date) : new Date(),
4706
+ updatedAt: u.updated_at ? new Date(u.updated_at) : new Date(),
4707
+ endDate: u.end_date ? new Date(u.end_date) : undefined,
4708
+ givenName: u.given_name || u.resource_given_name || '',
4709
+ resourceState: u.resource_state,
4710
+ resources: u.pod_resources,
4711
+ metadata: new Map(Object.entries(u.metadata || {})),
4712
+ }));
4713
+ return usages;
4675
4714
  },
4676
4715
  enabled: !!userId,
4677
4716
  ...options,
@@ -4688,13 +4727,29 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4688
4727
  url: `${configuration.iamRunUrl}/api/iam/v1/usage/platform`,
4689
4728
  method: 'GET',
4690
4729
  });
4691
- return resp.usages || [];
4730
+ // Transform snake_case API response to camelCase IUsage interface
4731
+ const usages = (resp.usages || []).map((u) => ({
4732
+ id: u.resource_uid,
4733
+ accountId: u.account_uid,
4734
+ type: u.resource_type,
4735
+ burningRate: u.burning_rate,
4736
+ credits: u.credits,
4737
+ creditsLimit: u.credits_limit,
4738
+ startDate: u.start_date ? new Date(u.start_date) : new Date(),
4739
+ updatedAt: u.updated_at ? new Date(u.updated_at) : new Date(),
4740
+ endDate: u.end_date ? new Date(u.end_date) : undefined,
4741
+ givenName: u.given_name || u.resource_given_name || '',
4742
+ resourceState: u.resource_state,
4743
+ resources: u.pod_resources,
4744
+ metadata: new Map(Object.entries(u.metadata || {})),
4745
+ }));
4746
+ return usages;
4692
4747
  },
4693
4748
  ...options,
4694
4749
  });
4695
4750
  };
4696
4751
  // ============================================================================
4697
- // [BATCH 10] Search Operations
4752
+ // Search Operations
4698
4753
  // ============================================================================
4699
4754
  /**
4700
4755
  * Search public items (notebooks, documents, etc.)
@@ -4722,7 +4777,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4722
4777
  });
4723
4778
  };
4724
4779
  // ============================================================================
4725
- // [BATCH 10] Social Media Integrations
4780
+ // Social Media Integrations
4726
4781
  // ============================================================================
4727
4782
  /**
4728
4783
  * Get GitHub profile from access token
@@ -4874,7 +4929,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4874
4929
  });
4875
4930
  };
4876
4931
  // ============================================================================
4877
- // [BATCH 10] Proxy Operations
4932
+ // Proxy Operations
4878
4933
  // ============================================================================
4879
4934
  /**
4880
4935
  * Proxy GET request
@@ -4933,7 +4988,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4933
4988
  });
4934
4989
  };
4935
4990
  // ============================================================================
4936
- // [BATCH 10] Waiting List & Growth
4991
+ // Waiting List & Growth
4937
4992
  // ============================================================================
4938
4993
  /**
4939
4994
  * Register to waiting list
@@ -4971,7 +5026,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4971
5026
  });
4972
5027
  };
4973
5028
  // ============================================================================
4974
- // BATCH 11: Refresh Operations & Additional Methods
5029
+ // Refresh Operations & Additional Methods
4975
5030
  // ============================================================================
4976
5031
  /**
4977
5032
  * Refresh a specific user space
@@ -5411,7 +5466,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
5411
5466
  });
5412
5467
  };
5413
5468
  // ============================================================================
5414
- // BATCH 12: Additional Refresh Operations
5469
+ // Additional Refresh Operations
5415
5470
  // ============================================================================
5416
5471
  /**
5417
5472
  * Refresh a specific environment
@@ -5646,7 +5701,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
5646
5701
  });
5647
5702
  };
5648
5703
  // ============================================================================
5649
- // BATCH 13: Final Methods - Invites, Contacts, Inbounds, Outbounds
5704
+ // Invites, Contacts, Inbounds, Outbounds
5650
5705
  // ============================================================================
5651
5706
  /**
5652
5707
  * Request an invite (mutation)
@@ -0,0 +1 @@
1
+ export declare function useIsMobile(): boolean;
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright (c) 2024-2025 Datalayer, Inc.
3
+ *
4
+ * BSD 3-Clause License
5
+ */
6
+ import * as React from 'react';
7
+ const MOBILE_BREAKPOINT = 768;
8
+ export function useIsMobile() {
9
+ const [isMobile, setIsMobile] = React.useState(undefined);
10
+ React.useEffect(() => {
11
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
12
+ const onChange = () => {
13
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
14
+ };
15
+ mql.addEventListener('change', onChange);
16
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
17
+ return () => {
18
+ mql.removeEventListener('change', onChange);
19
+ };
20
+ }, []);
21
+ return !!isMobile;
22
+ }