@datalayer/core 0.0.24 → 0.0.26

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 (70) hide show
  1. package/README.md +11 -11
  2. package/lib/api/index.d.ts +1 -1
  3. package/lib/api/index.js +1 -1
  4. package/lib/api/spacer/agentSpaces.d.ts +193 -0
  5. package/lib/api/spacer/agentSpaces.js +127 -0
  6. package/lib/api/spacer/index.d.ts +2 -1
  7. package/lib/api/spacer/index.js +2 -1
  8. package/lib/api/utils/validation.d.ts +1 -1
  9. package/lib/api/utils/validation.js +1 -1
  10. package/lib/client/auth/AuthenticationManager.d.ts +2 -2
  11. package/lib/client/auth/AuthenticationManager.js +2 -2
  12. package/lib/client/auth/index.d.ts +1 -1
  13. package/lib/client/auth/index.js +1 -1
  14. package/lib/client/auth/types.d.ts +1 -1
  15. package/lib/client/auth/types.js +1 -1
  16. package/lib/client/base.d.ts +9 -9
  17. package/lib/client/base.js +3 -3
  18. package/lib/client/constants.d.ts +2 -2
  19. package/lib/client/constants.js +2 -2
  20. package/lib/client/index.d.ts +2 -2
  21. package/lib/client/mixins/IAMMixin.js +1 -1
  22. package/lib/client/utils/spacerUtils.d.ts +1 -1
  23. package/lib/client/utils/spacerUtils.js +1 -1
  24. package/lib/components/progress/ConsumptionBar.js +19 -1
  25. package/lib/hooks/useCache.d.ts +95 -2
  26. package/lib/hooks/useCache.js +422 -9
  27. package/lib/hooks/useNavigate.d.ts +1 -1
  28. package/lib/hooks/useNavigate.js +11 -1
  29. package/lib/index.d.ts +1 -1
  30. package/lib/models/CreditsDTO.js +1 -1
  31. package/lib/models/Datasource.d.ts +2 -2
  32. package/lib/models/Datasource.js +2 -2
  33. package/lib/models/EnvironmentDTO.d.ts +3 -3
  34. package/lib/models/EnvironmentDTO.js +2 -2
  35. package/lib/models/HealthCheck.d.ts +1 -1
  36. package/lib/models/HealthCheck.js +1 -1
  37. package/lib/models/ItemDTO.d.ts +2 -2
  38. package/lib/models/ItemDTO.js +2 -2
  39. package/lib/models/LexicalDTO.d.ts +2 -2
  40. package/lib/models/LexicalDTO.js +2 -2
  41. package/lib/models/NotebookDTO.d.ts +2 -2
  42. package/lib/models/NotebookDTO.js +1 -1
  43. package/lib/models/RuntimeDTO.d.ts +2 -2
  44. package/lib/models/RuntimeDTO.js +2 -2
  45. package/lib/models/RuntimeSnapshotDTO.d.ts +3 -3
  46. package/lib/models/RuntimeSnapshotDTO.js +1 -1
  47. package/lib/models/Secret.d.ts +3 -3
  48. package/lib/models/Secret.js +2 -2
  49. package/lib/models/SpaceDTO.d.ts +2 -2
  50. package/lib/models/SpaceDTO.js +3 -3
  51. package/lib/models/UserDTO.d.ts +2 -2
  52. package/lib/models/UserDTO.js +1 -1
  53. package/lib/models/index.d.ts +1 -1
  54. package/lib/models/index.js +1 -1
  55. package/lib/state/substates/CoreState.js +1 -1
  56. package/lib/theme/DatalayerTheme.d.ts +17 -2
  57. package/lib/theme/DatalayerTheme.js +195 -29
  58. package/lib/theme/DatalayerThemeProvider.d.ts +22 -2
  59. package/lib/theme/DatalayerThemeProvider.js +48 -5
  60. package/lib/theme/index.d.ts +1 -0
  61. package/lib/theme/index.js +1 -0
  62. package/lib/theme/useSystemColorMode.d.ts +9 -0
  63. package/lib/theme/useSystemColorMode.js +26 -0
  64. package/lib/views/iam-tokens/IAMTokenNew.d.ts +5 -1
  65. package/lib/views/iam-tokens/IAMTokenNew.js +2 -2
  66. package/lib/views/iam-tokens/IAMTokens.d.ts +7 -1
  67. package/lib/views/iam-tokens/IAMTokens.js +6 -4
  68. package/package.json +3 -3
  69. package/lib/hooks/useCache0.d.ts +0 -312
  70. package/lib/hooks/useCache0.js +0 -3189
@@ -12,7 +12,7 @@ import { LexicalDTO } from '../../models/LexicalDTO';
12
12
  * to avoid code duplication.
13
13
  *
14
14
  * @param response - Raw API response containing space items
15
- * @param sdk - SDK instance to pass to model constructors
15
+ * @param sdk - Client instance to pass to model constructors
16
16
  * @returns Array of Notebook and Lexical model instances
17
17
  */
18
18
  export declare function convertSpaceItemsToModels(items: GetSpaceItemsResponse['items'], sdk: DatalayerClient): (NotebookDTO | LexicalDTO)[];
@@ -11,7 +11,7 @@ import { ItemTypes } from '../constants';
11
11
  * to avoid code duplication.
12
12
  *
13
13
  * @param response - Raw API response containing space items
14
- * @param sdk - SDK instance to pass to model constructors
14
+ * @param sdk - Client instance to pass to model constructors
15
15
  * @returns Array of Notebook and Lexical model instances
16
16
  */
17
17
  export function convertSpaceItemsToModels(items, sdk) {
@@ -9,6 +9,23 @@ import { Box } from '@datalayer/primer-addons';
9
9
  import { useInterval } from 'usehooks-ts';
10
10
  const CRITICAL_LEVEL = 90;
11
11
  const WARNING_LEVEL = 75;
12
+ /**
13
+ * Format seconds into a human-friendly string (e.g., "2h 15m", "45m", "30s")
14
+ */
15
+ function formatTimeRemaining(seconds) {
16
+ if (seconds < 0)
17
+ return '0s';
18
+ const hours = Math.floor(seconds / 3600);
19
+ const minutes = Math.floor((seconds % 3600) / 60);
20
+ const secs = Math.floor(seconds % 60);
21
+ if (hours > 0) {
22
+ return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
23
+ }
24
+ if (minutes > 0) {
25
+ return secs > 0 && minutes < 5 ? `${minutes}m ${secs}s` : `${minutes}m`;
26
+ }
27
+ return `${secs}s`;
28
+ }
12
29
  /**
13
30
  * Consumption progress bar
14
31
  */
@@ -36,8 +53,9 @@ export function ConsumptionBar(props) {
36
53
  : 'success.emphasis'
37
54
  : 'neutral.emphasis';
38
55
  const burntCredits = duration * burningRate;
56
+ const secondsRemaining = (1 - progress / 100) * duration;
39
57
  const title = duration
40
- ? `${((1 - progress / 100) * duration).toFixed(0)} seconds left - ${((progress / 100) * burntCredits).toFixed(2)} / ${burntCredits.toFixed(2)} credits`
58
+ ? `${formatTimeRemaining(secondsRemaining)} left - ${((progress / 100) * burntCredits).toFixed(2)} / ${burntCredits.toFixed(2)} credits`
41
59
  : `Started at ${new Date(startedAt * 1000).toISOString()} - ${burntCredits.toFixed(2)} credits consumed`;
42
60
  return (_jsx(_Fragment, { children: _jsx(Tooltip, { text: title, direction: "w", children: _jsx(Button, { variant: "invisible", children: _jsx(Box, { sx: { width: '70px' }, children: _jsx(ProgressBar, { tabIndex: onClick ? 0 : -1, style: style, animated: expiredAt ? false : true, bg: bg, progress: progress, onClick: onClick, onKeyDown: onClick
43
61
  ? event => {
@@ -36,6 +36,7 @@
36
36
  */
37
37
  import { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
38
38
  import { IAnyOrganization, IAnySpace, IAssignment, ICell, IContact, ICourse, IDataset, IDatasource, IDocument, IEnvironment, IExercise, IIAMToken, ILesson, INotebook, IOrganization, IPage, ISchool, ISecret, ITeam, IUser, IUserOnboarding, IUserSettings } from '../models';
39
+ import type { AgentSpaceData, CreateAgentSpaceRequest, UpdateAgentSpaceRequest } from '../api/spacer/agentSpaces';
39
40
  export type CacheProps = {
40
41
  loginRoute?: string;
41
42
  };
@@ -212,6 +213,19 @@ export declare const queryKeys: {
212
213
  readonly bySpace: (spaceId: string) => readonly ["items", "space", string];
213
214
  readonly search: (opts: ISearchOpts) => readonly ["items", "search", ISearchOpts];
214
215
  };
216
+ readonly agentSpaces: {
217
+ readonly all: () => readonly ["agentSpaces"];
218
+ readonly lists: () => readonly ["agentSpaces", "list"];
219
+ readonly details: () => readonly ["agentSpaces", "detail"];
220
+ readonly detail: (id: string) => readonly ["agentSpaces", "detail", string];
221
+ readonly public: () => readonly ["agentSpaces", "public"];
222
+ };
223
+ readonly agentRuntimes: {
224
+ readonly all: () => readonly ["agentRuntimes"];
225
+ readonly lists: () => readonly ["agentRuntimes", "list"];
226
+ readonly details: () => readonly ["agentRuntimes", "detail"];
227
+ readonly detail: (podName: string) => readonly ["agentRuntimes", "detail", string];
228
+ };
215
229
  readonly layout: {
216
230
  readonly byAccount: (accountHandle: string, spaceHandle?: string) => readonly ["layout", string, string] | readonly ["layout", string];
217
231
  };
@@ -297,7 +311,10 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
297
311
  token: string;
298
312
  }, unknown>;
299
313
  useOAuth2AuthorizationURL: () => import("@tanstack/react-query").UseMutationResult<string, Error, Record<string, string>, unknown>;
300
- useOAuth2AuthorizationLinkURL: () => import("@tanstack/react-query").UseMutationResult<string, Error, Record<string, string>, unknown>;
314
+ useOAuth2AuthorizationLinkURL: () => import("@tanstack/react-query").UseMutationResult<{
315
+ success: boolean;
316
+ autorization_url: string;
317
+ }, Error, Record<string, string>, unknown>;
301
318
  useGetGitHubProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
302
319
  useGetLinkedinProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
303
320
  usePostLinkedinShare: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
@@ -469,6 +486,67 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
469
486
  spaceHandle?: string;
470
487
  }, unknown>;
471
488
  useExportSpace: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
489
+ useAgentSpace: (uid: string | undefined) => import("@tanstack/react-query").UseQueryResult<AgentSpaceData, Error>;
490
+ useAgentSpaces: () => import("@tanstack/react-query").UseQueryResult<AgentSpaceData[], Error>;
491
+ usePublicAgentSpaces: () => import("@tanstack/react-query").UseQueryResult<AgentSpaceData[], Error>;
492
+ useCreateAgentSpace: () => import("@tanstack/react-query").UseMutationResult<any, Error, CreateAgentSpaceRequest, unknown>;
493
+ useUpdateAgentSpace: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
494
+ uid: string;
495
+ data: UpdateAgentSpaceRequest;
496
+ }, unknown>;
497
+ useDeleteAgentSpace: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
498
+ useMakeAgentSpacePublic: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
499
+ useMakeAgentSpacePrivate: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
500
+ useRefreshAgentSpace: () => (uid: string) => void;
501
+ useRefreshAgentSpaces: () => () => void;
502
+ useRefreshPublicAgentSpaces: () => () => void;
503
+ useAgentRuntime: (podName: string | undefined) => import("@tanstack/react-query").UseQueryResult<{
504
+ status: "running" | "paused" | "starting" | "terminated" | "archived";
505
+ name: string;
506
+ id: string;
507
+ url: string | undefined;
508
+ messageCount: number;
509
+ pod_name: string;
510
+ environment_name: string;
511
+ environment_title?: string;
512
+ given_name: string;
513
+ phase?: string;
514
+ type: string;
515
+ started_at?: string;
516
+ expired_at?: string;
517
+ burning_rate?: number;
518
+ ingress?: string;
519
+ token?: string;
520
+ agentSpec?: AgentSpaceData["agentSpec"];
521
+ }, Error>;
522
+ useAgentRuntimes: () => import("@tanstack/react-query").UseQueryResult<{
523
+ status: "running" | "paused" | "starting" | "terminated" | "archived";
524
+ name: string;
525
+ id: string;
526
+ url: string | undefined;
527
+ messageCount: number;
528
+ pod_name: string;
529
+ environment_name: string;
530
+ environment_title?: string;
531
+ given_name: string;
532
+ phase?: string;
533
+ type: string;
534
+ started_at?: string;
535
+ expired_at?: string;
536
+ burning_rate?: number;
537
+ ingress?: string;
538
+ token?: string;
539
+ agentSpec?: AgentSpaceData["agentSpec"];
540
+ }[], Error>;
541
+ useCreateAgentRuntime: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
542
+ environmentName?: string;
543
+ givenName?: string;
544
+ creditsLimit?: number;
545
+ type?: string;
546
+ editorVariant?: string;
547
+ }, unknown>;
548
+ useDeleteAgentRuntime: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
549
+ useRefreshAgentRuntimes: () => () => void;
472
550
  useCourse: (courseId: string) => import("@tanstack/react-query").UseQueryResult<ICourse | undefined, Error>;
473
551
  useUpdateCourse: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
474
552
  courseId: string;
@@ -655,7 +733,9 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
655
733
  useUpdateDatasource: () => import("@tanstack/react-query").UseMutationResult<any, Error, IDatasource, unknown>;
656
734
  useSecret: (secretId: string, options?: {
657
735
  enabled?: boolean;
658
- refetchOnMount?: boolean;
736
+ refetchOnMount?: boolean | "always";
737
+ staleTime?: number;
738
+ gcTime?: number;
659
739
  }) => import("@tanstack/react-query").UseQueryResult<ISecret | null | undefined, Error>;
660
740
  useSecrets: () => import("@tanstack/react-query").UseQueryResult<any, Error>;
661
741
  useCreateSecret: () => import("@tanstack/react-query").UseMutationResult<any, Error, Omit<ISecret, "id">, unknown>;
@@ -946,6 +1026,19 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
946
1026
  readonly bySpace: (spaceId: string) => readonly ["items", "space", string];
947
1027
  readonly search: (opts: ISearchOpts) => readonly ["items", "search", ISearchOpts];
948
1028
  };
1029
+ readonly agentSpaces: {
1030
+ readonly all: () => readonly ["agentSpaces"];
1031
+ readonly lists: () => readonly ["agentSpaces", "list"];
1032
+ readonly details: () => readonly ["agentSpaces", "detail"];
1033
+ readonly detail: (id: string) => readonly ["agentSpaces", "detail", string];
1034
+ readonly public: () => readonly ["agentSpaces", "public"];
1035
+ };
1036
+ readonly agentRuntimes: {
1037
+ readonly all: () => readonly ["agentRuntimes"];
1038
+ readonly lists: () => readonly ["agentRuntimes", "list"];
1039
+ readonly details: () => readonly ["agentRuntimes", "detail"];
1040
+ readonly detail: (podName: string) => readonly ["agentRuntimes", "detail", string];
1041
+ };
949
1042
  readonly layout: {
950
1043
  readonly byAccount: (accountHandle: string, spaceHandle?: string) => readonly ["layout", string, string] | readonly ["layout", string];
951
1044
  };
@@ -272,6 +272,21 @@ export const queryKeys = {
272
272
  bySpace: (spaceId) => [...queryKeys.items.all(), 'space', spaceId],
273
273
  search: (opts) => [...queryKeys.items.all(), 'search', opts],
274
274
  },
275
+ // Agent Spaces
276
+ agentSpaces: {
277
+ all: () => ['agentSpaces'],
278
+ lists: () => [...queryKeys.agentSpaces.all(), 'list'],
279
+ details: () => [...queryKeys.agentSpaces.all(), 'detail'],
280
+ detail: (id) => [...queryKeys.agentSpaces.details(), id],
281
+ public: () => [...queryKeys.agentSpaces.all(), 'public'],
282
+ },
283
+ // Agent Runtimes (runtimes with ai-agents environment)
284
+ agentRuntimes: {
285
+ all: () => ['agentRuntimes'],
286
+ lists: () => [...queryKeys.agentRuntimes.all(), 'list'],
287
+ details: () => [...queryKeys.agentRuntimes.all(), 'detail'],
288
+ detail: (podName) => [...queryKeys.agentRuntimes.details(), podName],
289
+ },
275
290
  // Layout
276
291
  layout: {
277
292
  byAccount: (accountHandle, spaceHandle) => spaceHandle
@@ -1334,6 +1349,386 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
1334
1349
  });
1335
1350
  };
1336
1351
  // ============================================================================
1352
+ // Agent Spaces Hooks
1353
+ // ============================================================================
1354
+ /**
1355
+ * Get agent space by ID
1356
+ */
1357
+ const useAgentSpace = (uid) => {
1358
+ return useQuery({
1359
+ queryKey: queryKeys.agentSpaces.detail(uid || ''),
1360
+ queryFn: async () => {
1361
+ const resp = await requestDatalayer({
1362
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/agent-spaces/${uid}`,
1363
+ method: 'GET',
1364
+ });
1365
+ if (resp.success && resp.agentSpace) {
1366
+ return resp.agentSpace;
1367
+ }
1368
+ throw new Error(resp.message || 'Failed to fetch agent space');
1369
+ },
1370
+ ...DEFAULT_QUERY_OPTIONS,
1371
+ enabled: !!uid,
1372
+ });
1373
+ };
1374
+ /**
1375
+ * List user's agent spaces
1376
+ */
1377
+ const useAgentSpaces = () => {
1378
+ return useQuery({
1379
+ queryKey: queryKeys.agentSpaces.lists(),
1380
+ queryFn: async () => {
1381
+ const resp = await requestDatalayer({
1382
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/agent-spaces`,
1383
+ method: 'GET',
1384
+ });
1385
+ if (resp.success && resp.agentSpaces) {
1386
+ const agentSpaces = resp.agentSpaces;
1387
+ // Set detail cache for each agent space
1388
+ agentSpaces.forEach((agentSpace) => {
1389
+ queryClient.setQueryData(queryKeys.agentSpaces.detail(agentSpace.id), agentSpace);
1390
+ });
1391
+ return agentSpaces;
1392
+ }
1393
+ return [];
1394
+ },
1395
+ ...DEFAULT_QUERY_OPTIONS,
1396
+ enabled: !!user,
1397
+ });
1398
+ };
1399
+ /**
1400
+ * List public agent spaces (Library)
1401
+ */
1402
+ const usePublicAgentSpaces = () => {
1403
+ return useQuery({
1404
+ queryKey: queryKeys.agentSpaces.public(),
1405
+ queryFn: async () => {
1406
+ const resp = await requestDatalayer({
1407
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/agent-spaces/public`,
1408
+ method: 'GET',
1409
+ });
1410
+ if (resp.success && resp.agentSpaces) {
1411
+ return resp.agentSpaces;
1412
+ }
1413
+ return [];
1414
+ },
1415
+ ...DEFAULT_QUERY_OPTIONS,
1416
+ });
1417
+ };
1418
+ /**
1419
+ * Create agent space
1420
+ */
1421
+ const useCreateAgentSpace = () => {
1422
+ return useMutation({
1423
+ mutationFn: async (data) => {
1424
+ return requestDatalayer({
1425
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/agent-spaces`,
1426
+ method: 'POST',
1427
+ body: data,
1428
+ });
1429
+ },
1430
+ onSuccess: resp => {
1431
+ if (resp.success && resp.agentSpace) {
1432
+ const agentSpace = resp.agentSpace;
1433
+ // Set detail cache
1434
+ queryClient.setQueryData(queryKeys.agentSpaces.detail(agentSpace.id), agentSpace);
1435
+ // Invalidate all agent space queries
1436
+ queryClient.invalidateQueries({
1437
+ queryKey: queryKeys.agentSpaces.all(),
1438
+ });
1439
+ }
1440
+ },
1441
+ });
1442
+ };
1443
+ /**
1444
+ * Update agent space
1445
+ */
1446
+ const useUpdateAgentSpace = () => {
1447
+ return useMutation({
1448
+ mutationFn: async ({ uid, data, }) => {
1449
+ return requestDatalayer({
1450
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/agent-spaces/${uid}`,
1451
+ method: 'PUT',
1452
+ body: data,
1453
+ });
1454
+ },
1455
+ onSuccess: (resp, { uid }) => {
1456
+ if (resp.success) {
1457
+ // Invalidate detail cache
1458
+ queryClient.invalidateQueries({
1459
+ queryKey: queryKeys.agentSpaces.detail(uid),
1460
+ });
1461
+ // Invalidate all agent space queries
1462
+ queryClient.invalidateQueries({
1463
+ queryKey: queryKeys.agentSpaces.all(),
1464
+ });
1465
+ }
1466
+ },
1467
+ });
1468
+ };
1469
+ /**
1470
+ * Delete agent space
1471
+ */
1472
+ const useDeleteAgentSpace = () => {
1473
+ return useMutation({
1474
+ mutationFn: async (uid) => {
1475
+ return requestDatalayer({
1476
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/agent-spaces/${uid}`,
1477
+ method: 'DELETE',
1478
+ });
1479
+ },
1480
+ onSuccess: () => {
1481
+ // Invalidate all agent space queries
1482
+ queryClient.invalidateQueries({
1483
+ queryKey: queryKeys.agentSpaces.all(),
1484
+ });
1485
+ },
1486
+ });
1487
+ };
1488
+ /**
1489
+ * Make agent space public
1490
+ */
1491
+ const useMakeAgentSpacePublic = () => {
1492
+ return useMutation({
1493
+ mutationFn: async (uid) => {
1494
+ return requestDatalayer({
1495
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/agent-spaces/${uid}/public`,
1496
+ method: 'POST',
1497
+ });
1498
+ },
1499
+ onSuccess: (resp, uid) => {
1500
+ if (resp.success) {
1501
+ queryClient.invalidateQueries({
1502
+ queryKey: queryKeys.agentSpaces.detail(uid),
1503
+ });
1504
+ queryClient.invalidateQueries({
1505
+ queryKey: queryKeys.agentSpaces.all(),
1506
+ });
1507
+ }
1508
+ },
1509
+ });
1510
+ };
1511
+ /**
1512
+ * Make agent space private
1513
+ */
1514
+ const useMakeAgentSpacePrivate = () => {
1515
+ return useMutation({
1516
+ mutationFn: async (uid) => {
1517
+ return requestDatalayer({
1518
+ url: `${configuration.spacerRunUrl}/api/spacer/v1/agent-spaces/${uid}/private`,
1519
+ method: 'POST',
1520
+ });
1521
+ },
1522
+ onSuccess: (resp, uid) => {
1523
+ if (resp.success) {
1524
+ queryClient.invalidateQueries({
1525
+ queryKey: queryKeys.agentSpaces.detail(uid),
1526
+ });
1527
+ queryClient.invalidateQueries({
1528
+ queryKey: queryKeys.agentSpaces.all(),
1529
+ });
1530
+ }
1531
+ },
1532
+ });
1533
+ };
1534
+ /**
1535
+ * Refresh agent space data
1536
+ */
1537
+ const useRefreshAgentSpace = () => {
1538
+ return (uid) => {
1539
+ queryClient.invalidateQueries({
1540
+ queryKey: queryKeys.agentSpaces.detail(uid),
1541
+ });
1542
+ };
1543
+ };
1544
+ /**
1545
+ * Refresh agent spaces list
1546
+ */
1547
+ const useRefreshAgentSpaces = () => {
1548
+ return () => {
1549
+ queryClient.invalidateQueries({
1550
+ queryKey: queryKeys.agentSpaces.all(),
1551
+ });
1552
+ };
1553
+ };
1554
+ /**
1555
+ * Refresh public agent spaces list
1556
+ */
1557
+ const useRefreshPublicAgentSpaces = () => {
1558
+ return () => {
1559
+ queryClient.invalidateQueries({
1560
+ queryKey: queryKeys.agentSpaces.public(),
1561
+ });
1562
+ };
1563
+ };
1564
+ /**
1565
+ * List agent runtimes (runtimes with ai-agents-env environment)
1566
+ */
1567
+ /**
1568
+ * Get all agent runtimes for the current user.
1569
+ *
1570
+ * Note on phase/status mapping:
1571
+ * The backend (operator) RuntimePod model does not include a 'phase' field.
1572
+ * The operator only keeps active/assigned runtimes in its cache (OperatorCache.USER_RUNTIMES),
1573
+ * so any runtime returned by this endpoint is inherently running or starting.
1574
+ * Therefore, if rt.phase is undefined (which it will be), we default to 'running'.
1575
+ * A 'paused' state would require explicit backend support to track paused runtimes.
1576
+ */
1577
+ const useAgentRuntimes = () => {
1578
+ return useQuery({
1579
+ queryKey: queryKeys.agentRuntimes.lists(),
1580
+ queryFn: async () => {
1581
+ const resp = await requestDatalayer({
1582
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/runtimes`,
1583
+ method: 'GET',
1584
+ });
1585
+ if (resp.success && resp.runtimes) {
1586
+ // Filter to only include ai-agents-env runtimes
1587
+ const agentRuntimes = resp.runtimes
1588
+ .filter((rt) => rt.environment_name === 'ai-agents-env')
1589
+ .map((rt) => ({
1590
+ ...rt,
1591
+ // Phase/status mapping: see hook JSDoc for details.
1592
+ // Backend returns only active runtimes, so default to 'running'.
1593
+ status: rt.phase === 'Pending'
1594
+ ? 'starting'
1595
+ : rt.phase === 'Terminated'
1596
+ ? 'terminated'
1597
+ : rt.phase === 'Paused'
1598
+ ? 'paused'
1599
+ : rt.phase === 'Archived'
1600
+ ? 'archived'
1601
+ : 'running',
1602
+ name: rt.given_name || rt.pod_name,
1603
+ id: rt.pod_name,
1604
+ // Map ingress URL to url for UI consistency
1605
+ url: rt.ingress,
1606
+ messageCount: 0, // Default for UI compatibility
1607
+ }));
1608
+ // Set detail cache for each runtime
1609
+ agentRuntimes.forEach((runtime) => {
1610
+ queryClient.setQueryData(queryKeys.agentRuntimes.detail(runtime.pod_name), runtime);
1611
+ });
1612
+ return agentRuntimes;
1613
+ }
1614
+ return [];
1615
+ },
1616
+ ...DEFAULT_QUERY_OPTIONS,
1617
+ refetchInterval: 10000, // Refetch every 10 seconds for status updates
1618
+ enabled: !!user,
1619
+ });
1620
+ };
1621
+ /**
1622
+ * Get a single agent runtime by pod name.
1623
+ *
1624
+ * Note on phase/status mapping:
1625
+ * Same as useAgentRuntimes - the backend RuntimePod model has no 'phase' field,
1626
+ * and only active runtimes exist in the operator cache. Default to 'running'.
1627
+ */
1628
+ const useAgentRuntime = (podName) => {
1629
+ return useQuery({
1630
+ queryKey: queryKeys.agentRuntimes.detail(podName ?? ''),
1631
+ queryFn: async () => {
1632
+ const resp = await requestDatalayer({
1633
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/runtimes/${podName}`,
1634
+ method: 'GET',
1635
+ });
1636
+ if (resp.runtime) {
1637
+ const rt = resp.runtime;
1638
+ return {
1639
+ ...rt,
1640
+ // Phase/status mapping: see useAgentRuntimes JSDoc for details.
1641
+ status: rt.phase === 'Pending'
1642
+ ? 'starting'
1643
+ : rt.phase === 'Terminated'
1644
+ ? 'terminated'
1645
+ : rt.phase === 'Paused'
1646
+ ? 'paused'
1647
+ : rt.phase === 'Archived'
1648
+ ? 'archived'
1649
+ : 'running',
1650
+ name: rt.given_name || rt.pod_name,
1651
+ id: rt.pod_name,
1652
+ // Map ingress URL to url for UI consistency
1653
+ url: rt.ingress,
1654
+ messageCount: 0,
1655
+ };
1656
+ }
1657
+ throw new Error('Failed to fetch agent runtime');
1658
+ },
1659
+ ...DEFAULT_QUERY_OPTIONS,
1660
+ refetchInterval: 5000, // Refetch every 5 seconds for status
1661
+ enabled: !!podName,
1662
+ });
1663
+ };
1664
+ const useCreateAgentRuntime = () => {
1665
+ return useMutation({
1666
+ mutationFn: async (data) => {
1667
+ return requestDatalayer({
1668
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/runtimes`,
1669
+ method: 'POST',
1670
+ body: {
1671
+ environment_name: data.environmentName || 'ai-agents-env',
1672
+ given_name: data.givenName || 'Agent Space',
1673
+ credits_limit: data.creditsLimit || 10,
1674
+ type: data.type || 'notebook',
1675
+ editor_variant: data.editorVariant || 'none',
1676
+ },
1677
+ });
1678
+ },
1679
+ onSuccess: resp => {
1680
+ if (resp.success && resp.runtime) {
1681
+ const rt = resp.runtime;
1682
+ // Phase/status mapping: see useAgentRuntimes JSDoc for details.
1683
+ queryClient.setQueryData(queryKeys.agentRuntimes.detail(rt.pod_name), {
1684
+ ...rt,
1685
+ status: rt.phase === 'Pending'
1686
+ ? 'starting'
1687
+ : 'running',
1688
+ name: rt.given_name || rt.pod_name,
1689
+ id: rt.pod_name,
1690
+ // Map ingress URL to url for UI consistency
1691
+ url: rt.ingress,
1692
+ messageCount: 0,
1693
+ });
1694
+ // Invalidate list
1695
+ queryClient.invalidateQueries({
1696
+ queryKey: queryKeys.agentRuntimes.all(),
1697
+ });
1698
+ }
1699
+ },
1700
+ });
1701
+ };
1702
+ /**
1703
+ * Delete agent runtime
1704
+ */
1705
+ const useDeleteAgentRuntime = () => {
1706
+ return useMutation({
1707
+ mutationFn: async (podName) => {
1708
+ return requestDatalayer({
1709
+ url: `${configuration.runtimesRunUrl}/api/runtimes/v1/runtimes/${podName}`,
1710
+ method: 'DELETE',
1711
+ });
1712
+ },
1713
+ onSuccess: () => {
1714
+ // Invalidate all agent runtime queries
1715
+ queryClient.invalidateQueries({
1716
+ queryKey: queryKeys.agentRuntimes.all(),
1717
+ });
1718
+ },
1719
+ });
1720
+ };
1721
+ /**
1722
+ * Refresh agent runtimes list
1723
+ */
1724
+ const useRefreshAgentRuntimes = () => {
1725
+ return () => {
1726
+ queryClient.invalidateQueries({
1727
+ queryKey: queryKeys.agentRuntimes.all(),
1728
+ });
1729
+ };
1730
+ };
1731
+ // ============================================================================
1337
1732
  // Notebook Hooks
1338
1733
  // ============================================================================
1339
1734
  /**
@@ -1834,6 +2229,10 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
1834
2229
  /**
1835
2230
  * Get all secrets
1836
2231
  */
2232
+ // TODO: Previously this hook pre-populated individual secret caches with setQueryData,
2233
+ // but this prevented useSecret from fetching fresh data (e.g., the value field).
2234
+ // Consider re-adding cache pre-population if the list endpoint returns full secret data,
2235
+ // or use a different query key pattern for partial vs full secret data.
1837
2236
  const useSecrets = () => {
1838
2237
  return useQuery({
1839
2238
  queryKey: queryKeys.secrets.all(),
@@ -1844,13 +2243,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
1844
2243
  });
1845
2244
  if (resp.success && resp.secrets) {
1846
2245
  const secrets = resp.secrets
1847
- .map((s) => {
1848
- const secret = toSecret(s);
1849
- if (secret) {
1850
- queryClient.setQueryData(queryKeys.secrets.detail(secret.id), secret);
1851
- }
1852
- return secret;
1853
- })
2246
+ .map((s) => toSecret(s))
1854
2247
  .filter(Boolean);
1855
2248
  return secrets;
1856
2249
  }
@@ -2208,6 +2601,8 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
2208
2601
  ...DEFAULT_QUERY_OPTIONS,
2209
2602
  enabled: options?.enabled ?? !!secretId,
2210
2603
  refetchOnMount: options?.refetchOnMount ?? DEFAULT_QUERY_OPTIONS.refetchOnMount,
2604
+ staleTime: options?.staleTime ?? DEFAULT_QUERY_OPTIONS.staleTime,
2605
+ gcTime: options?.gcTime ?? DEFAULT_QUERY_OPTIONS.gcTime,
2211
2606
  });
2212
2607
  };
2213
2608
  /**
@@ -4485,7 +4880,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4485
4880
  const resp = await requestDatalayer({
4486
4881
  url: `${configuration.iamRunUrl}/api/iam/v1/oauth2/authz/url/link?${queryString}`,
4487
4882
  });
4488
- return resp.autorization_url;
4883
+ return resp;
4489
4884
  },
4490
4885
  });
4491
4886
  };
@@ -4835,7 +5230,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
4835
5230
  method: 'POST',
4836
5231
  body: {
4837
5232
  request_method: 'GET',
4838
- request_url: 'https://api.linkedin.com/v2/me',
5233
+ request_url: 'https://api.linkedin.com/v2/userinfo',
4839
5234
  request_token: accessToken,
4840
5235
  },
4841
5236
  });
@@ -6032,6 +6427,24 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
6032
6427
  useRefreshUserSpace,
6033
6428
  useRefreshLayout,
6034
6429
  useExportSpace,
6430
+ // Agent Spaces
6431
+ useAgentSpace,
6432
+ useAgentSpaces,
6433
+ usePublicAgentSpaces,
6434
+ useCreateAgentSpace,
6435
+ useUpdateAgentSpace,
6436
+ useDeleteAgentSpace,
6437
+ useMakeAgentSpacePublic,
6438
+ useMakeAgentSpacePrivate,
6439
+ useRefreshAgentSpace,
6440
+ useRefreshAgentSpaces,
6441
+ useRefreshPublicAgentSpaces,
6442
+ // Agent Runtimes (runtimes with ai-agents environment)
6443
+ useAgentRuntime,
6444
+ useAgentRuntimes,
6445
+ useCreateAgentRuntime,
6446
+ useDeleteAgentRuntime,
6447
+ useRefreshAgentRuntimes,
6035
6448
  // Courses
6036
6449
  useCourse,
6037
6450
  useUpdateCourse,