@datalayer/core 0.0.16 → 0.0.18

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 (133) hide show
  1. package/README.md +9 -13
  2. package/lib/client/auth/AuthenticationManager.d.ts +95 -0
  3. package/lib/client/auth/AuthenticationManager.js +214 -0
  4. package/lib/client/auth/index.d.ts +8 -0
  5. package/lib/client/auth/index.js +17 -0
  6. package/lib/client/auth/storage.d.ts +154 -0
  7. package/lib/client/auth/storage.js +447 -0
  8. package/lib/client/auth/strategies.d.ts +54 -0
  9. package/lib/client/auth/strategies.js +238 -0
  10. package/lib/client/auth/types.d.ts +151 -0
  11. package/lib/{examples/index.js → client/auth/types.js} +4 -2
  12. package/lib/client/base.d.ts +3 -0
  13. package/lib/client/base.js +9 -0
  14. package/lib/client/index.d.ts +1 -0
  15. package/lib/client/index.js +2 -0
  16. package/lib/components/auth/Login.d.ts +40 -0
  17. package/lib/components/auth/Login.js +173 -0
  18. package/lib/components/auth/Login.stories.d.ts +54 -0
  19. package/lib/components/auth/Login.stories.js +104 -0
  20. package/lib/components/auth/LoginToken.d.ts +16 -0
  21. package/lib/components/auth/LoginToken.js +63 -0
  22. package/lib/components/auth/index.d.ts +5 -0
  23. package/lib/components/auth/index.js +16 -0
  24. package/lib/components/avatars/BoringAvatar.d.ts +6 -15
  25. package/lib/components/avatars/BoringAvatar.js +30 -34
  26. package/lib/components/avatars/BoringAvatar.stories.d.ts +7 -16
  27. package/lib/components/avatars/UserProfileAvatar.d.ts +1 -6
  28. package/lib/components/avatars/UserProfileAvatar.js +3 -8
  29. package/lib/components/buttons/DownloadCSVButton.d.ts +2 -7
  30. package/lib/components/buttons/DownloadCSVButton.js +1 -5
  31. package/lib/components/buttons/DownloadJsonButton.d.ts +3 -10
  32. package/lib/components/buttons/DownloadJsonButton.js +1 -7
  33. package/lib/components/buttons/UploadButton.d.ts +1 -4
  34. package/lib/components/buttons/UploadButton.js +3 -7
  35. package/lib/components/chat/ChatComponent.d.ts +4 -0
  36. package/lib/components/chat/ChatComponent.js +143 -0
  37. package/lib/components/chat/MessagePart.d.ts +11 -0
  38. package/lib/components/chat/MessagePart.js +23 -0
  39. package/lib/components/chat/display/DynamicToolPart.d.ts +6 -0
  40. package/lib/components/chat/display/DynamicToolPart.js +5 -0
  41. package/lib/components/chat/display/ReasoningPart.d.ts +6 -0
  42. package/lib/components/chat/display/ReasoningPart.js +58 -0
  43. package/lib/components/chat/display/TextPart.d.ts +9 -0
  44. package/lib/components/chat/display/TextPart.js +93 -0
  45. package/lib/components/chat/display/ToolPart.d.ts +6 -0
  46. package/lib/components/chat/display/ToolPart.js +148 -0
  47. package/lib/components/chat/display/index.d.ts +4 -0
  48. package/lib/components/chat/display/index.js +13 -0
  49. package/lib/components/chat/handler.d.ts +8 -0
  50. package/lib/components/chat/handler.js +43 -0
  51. package/lib/components/chat/index.d.ts +4 -0
  52. package/lib/components/chat/index.js +13 -0
  53. package/lib/components/display/CenteredSpinner.d.ts +1 -4
  54. package/lib/components/display/CenteredSpinner.js +1 -5
  55. package/lib/components/display/HorizontalCenter.d.ts +1 -4
  56. package/lib/components/display/HorizontalCenter.js +1 -5
  57. package/lib/components/flashes/FlashClosable.d.ts +1 -4
  58. package/lib/components/flashes/FlashClosable.js +1 -5
  59. package/lib/components/flashes/FlashDisclaimer.js +1 -1
  60. package/lib/components/index.d.ts +2 -1
  61. package/lib/components/index.js +2 -1
  62. package/lib/components/notebooks/JupyterNotebook.d.ts +1 -6
  63. package/lib/components/notebooks/JupyterNotebook.js +1 -5
  64. package/lib/components/runtimes/RuntimeSimplePicker.d.ts +4 -0
  65. package/lib/components/runtimes/RuntimeSimplePicker.js +3 -3
  66. package/lib/components/snapshots/RuntimeSnapshotMenu.d.ts +1 -4
  67. package/lib/components/snapshots/RuntimeSnapshotMenu.js +1 -5
  68. package/lib/config/Configuration.js +1 -1
  69. package/lib/examples/CellExample.js +11 -47
  70. package/lib/examples/lexical-theme.css +436 -0
  71. package/lib/examples/notebooks/Matplotlib.ipynb.json +1 -1
  72. package/lib/examples/notebooks/NotebookExample1.ipynb.json +1 -1
  73. package/lib/hooks/useAIJupyterChat.d.ts +36 -0
  74. package/lib/hooks/useAIJupyterChat.js +53 -0
  75. package/lib/hooks/useBackdrop.d.ts +4 -4
  76. package/lib/hooks/useBackdrop.js +5 -9
  77. package/lib/hooks/useCache.d.ts +5 -1
  78. package/lib/hooks/useCache.js +126 -58
  79. package/lib/hooks/useMobile.d.ts +1 -0
  80. package/lib/hooks/useMobile.js +26 -0
  81. package/lib/hooks/useScreenshot.d.ts +3 -5
  82. package/lib/hooks/useScreenshot.js +1 -8
  83. package/lib/hooks/useUpload.js +29 -21
  84. package/lib/index.d.ts +1 -0
  85. package/lib/index.js +8 -4
  86. package/lib/models/Outbound.d.ts +2 -0
  87. package/lib/models/Outbound.js +3 -1
  88. package/lib/state/substates/CoreState.js +1 -1
  89. package/lib/state/substates/IAMState.js +15 -6
  90. package/lib/stateful/index.d.ts +0 -1
  91. package/lib/stateful/index.js +0 -1
  92. package/lib/stateful/runtimes/actions.d.ts +1 -1
  93. package/lib/stateful/runtimes/actions.js +1 -1
  94. package/lib/theme/DatalayerTheme.d.ts +2 -2
  95. package/lib/theme/DatalayerTheme.js +4 -4
  96. package/lib/theme/DatalayerThemeProvider.js +2 -2
  97. package/lib/tools/adapters/agui/AgUIToolAdapter.d.ts +75 -0
  98. package/lib/tools/adapters/agui/AgUIToolAdapter.js +244 -0
  99. package/lib/tools/adapters/agui/index.d.ts +10 -0
  100. package/lib/tools/adapters/agui/index.js +19 -0
  101. package/lib/tools/adapters/agui/lexicalHooks.d.ts +27 -0
  102. package/lib/tools/adapters/agui/lexicalHooks.js +64 -0
  103. package/lib/tools/adapters/agui/notebookHooks.d.ts +27 -0
  104. package/lib/tools/adapters/agui/notebookHooks.js +61 -0
  105. package/lib/tools/index.d.ts +6 -0
  106. package/lib/tools/index.js +18 -0
  107. package/lib/types.d.ts +5 -0
  108. package/lib/types.js +5 -0
  109. package/lib/utils/cli/index.d.ts +4 -0
  110. package/lib/utils/cli/index.js +13 -0
  111. package/lib/utils/cli/query.d.ts +6 -0
  112. package/lib/utils/cli/query.js +26 -0
  113. package/lib/utils/index.d.ts +1 -0
  114. package/lib/utils/index.js +1 -0
  115. package/package.json +62 -5
  116. package/style/base.css +4 -0
  117. package/lib/examples/DatalayerNotebookExample.d.ts +0 -16
  118. package/lib/examples/DatalayerNotebookExample.js +0 -75
  119. package/lib/examples/NativeNavigationExample.d.ts +0 -8
  120. package/lib/examples/NativeNavigationExample.js +0 -97
  121. package/lib/examples/NotebookMutationsKernel.d.ts +0 -2
  122. package/lib/examples/NotebookMutationsKernel.js +0 -115
  123. package/lib/examples/NotebookMutationsServiceManager.d.ts +0 -2
  124. package/lib/examples/NotebookMutationsServiceManager.js +0 -107
  125. package/lib/examples/ReactRouterExample.d.ts +0 -6
  126. package/lib/examples/ReactRouterExample.js +0 -175
  127. package/lib/examples/example-selector.d.ts +0 -22
  128. package/lib/examples/example-selector.js +0 -45
  129. package/lib/examples/index.d.ts +0 -2
  130. package/lib/examples/main.d.ts +0 -1
  131. package/lib/examples/main.js +0 -153
  132. package/lib/examples/notebooks/OutputIPyWidgetsExample.d.ts +0 -145
  133. package/lib/examples/notebooks/OutputIPyWidgetsExample.js +0 -153
@@ -0,0 +1,143 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2023-2025 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /*
7
+ * Copyright (c) 2024-2025 Datalayer, Inc.
8
+ *
9
+ * BSD 3-Clause License
10
+ */
11
+ import { useState, useEffect, useMemo, useRef } from 'react';
12
+ import { useQuery } from '@tanstack/react-query';
13
+ import { Box, Button, IconButton, Textarea, FormControl, Spinner, ActionMenu, ActionList, Text, } from '@primer/react';
14
+ import { ToolsIcon, ArrowUpIcon, ArrowDownIcon, AiModelIcon, } from '@primer/octicons-react';
15
+ import { useAIJupyterChat } from '../../hooks/useAIJupyterChat';
16
+ import { requestAPI } from './handler';
17
+ import { MessagePart } from './MessagePart';
18
+ async function getModels() {
19
+ return await requestAPI('configure');
20
+ }
21
+ /**
22
+ * Main Chat component using Primer React
23
+ */
24
+ export const ChatComponent = () => {
25
+ const [model, setModel] = useState('');
26
+ const [enabledTools, setEnabledTools] = useState([]);
27
+ const [inputValue, setInputValue] = useState('');
28
+ const [showScrollButton, setShowScrollButton] = useState(false);
29
+ const { messages, sendMessage, status, regenerate } = useAIJupyterChat();
30
+ const textareaRef = useRef(null);
31
+ const messagesEndRef = useRef(null);
32
+ const scrollContainerRef = useRef(null);
33
+ const configQuery = useQuery({
34
+ queryFn: getModels,
35
+ queryKey: ['models'],
36
+ });
37
+ useEffect(() => {
38
+ if (configQuery.data) {
39
+ setModel(configQuery.data.models[0].id);
40
+ // Enable all builtin tools by default
41
+ const allToolIds = configQuery.data.builtinTools?.map(tool => tool.id) || [];
42
+ setEnabledTools(allToolIds);
43
+ }
44
+ }, [configQuery.data]);
45
+ // Auto-scroll to bottom when new messages arrive
46
+ useEffect(() => {
47
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
48
+ }, [messages]);
49
+ // Handle scroll to show/hide scroll button
50
+ useEffect(() => {
51
+ const container = scrollContainerRef.current;
52
+ if (!container)
53
+ return;
54
+ const handleScroll = () => {
55
+ const isScrolledUp = container.scrollHeight - container.scrollTop - container.clientHeight >
56
+ 100;
57
+ setShowScrollButton(isScrolledUp);
58
+ };
59
+ container.addEventListener('scroll', handleScroll);
60
+ return () => container.removeEventListener('scroll', handleScroll);
61
+ }, []);
62
+ const handleSubmit = (e) => {
63
+ e.preventDefault();
64
+ if (inputValue.trim() && status !== 'streaming') {
65
+ sendMessage({ text: inputValue }, {
66
+ body: { model, builtinTools: enabledTools },
67
+ }).catch((error) => {
68
+ console.error('Error sending message:', error);
69
+ });
70
+ setInputValue('');
71
+ textareaRef.current?.focus();
72
+ }
73
+ };
74
+ const handleKeyDown = (e) => {
75
+ if (e.key === 'Enter' && !e.shiftKey) {
76
+ e.preventDefault();
77
+ handleSubmit(e);
78
+ }
79
+ };
80
+ const regen = (id) => {
81
+ regenerate({ messageId: id }).catch((error) => {
82
+ console.error('Error regenerating message:', error);
83
+ });
84
+ };
85
+ const scrollToBottom = () => {
86
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
87
+ };
88
+ const availableTools = useMemo(() => {
89
+ if (!configQuery.data)
90
+ return [];
91
+ const selectedModel = configQuery.data.models.find(entry => entry.id === model);
92
+ const enabledToolIds = selectedModel?.builtinTools ?? [];
93
+ // If model doesn't specify tools, show all builtin tools
94
+ const tools = enabledToolIds.length > 0
95
+ ? (configQuery.data.builtinTools?.filter(tool => enabledToolIds.includes(tool.id)) ?? [])
96
+ : (configQuery.data.builtinTools ?? []);
97
+ return tools;
98
+ }, [configQuery.data, model]);
99
+ return (_jsxs(Box, { className: "dla-chat-root", sx: {
100
+ position: 'absolute',
101
+ top: 0,
102
+ left: 0,
103
+ right: 0,
104
+ bottom: 0,
105
+ display: 'flex',
106
+ flexDirection: 'column',
107
+ }, children: [_jsxs(Box, { ref: scrollContainerRef, className: "dla-chat-messages", sx: {
108
+ position: 'absolute',
109
+ top: 0,
110
+ left: 0,
111
+ right: 0,
112
+ bottom: 0,
113
+ overflowY: 'scroll',
114
+ overflowX: 'hidden',
115
+ padding: 3,
116
+ paddingBottom: '180px',
117
+ }, children: [messages.map(message => (_jsx(Box, { sx: { marginBottom: 3 }, children: message.parts.map((part, index) => (_jsx(MessagePart, { part: part, message: message, status: status, index: index, regen: regen, lastMessage: message.id === messages.at(-1)?.id }, `${message.id}-${index}`))) }, message.id))), status === 'submitted' && (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', padding: 3 }, children: _jsx(Spinner, { size: "medium" }) })), _jsx("div", { ref: messagesEndRef })] }), showScrollButton && (_jsx(Box, { sx: {
118
+ position: 'absolute',
119
+ bottom: 160,
120
+ right: 16,
121
+ zIndex: 1,
122
+ }, children: _jsx(IconButton, { icon: ArrowDownIcon, "aria-label": "Scroll to bottom", onClick: scrollToBottom, variant: "default", size: "medium" }) })), _jsx(Box, { sx: {
123
+ position: 'absolute',
124
+ bottom: 0,
125
+ left: 0,
126
+ right: 0,
127
+ borderTop: '1px solid',
128
+ borderColor: 'border.default',
129
+ padding: 3,
130
+ backgroundColor: 'canvas.default',
131
+ zIndex: 0,
132
+ }, children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(FormControl, { sx: { width: '100%' }, children: _jsx(Textarea, { ref: textareaRef, value: inputValue, onChange: e => setInputValue(e.target.value), onKeyDown: handleKeyDown, placeholder: "Ask me anything...", rows: 3, resize: "vertical", sx: { marginBottom: 2, width: '100%' } }) }), _jsxs(Box, { sx: {
133
+ display: 'flex',
134
+ justifyContent: 'space-between',
135
+ alignItems: 'center',
136
+ }, children: [_jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center' }, children: [availableTools.length > 0 && (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: ToolsIcon, "aria-label": "Tools", variant: "invisible", size: "small" }) }), _jsx(ActionMenu.Overlay, { children: _jsx(ActionList, { children: _jsx(ActionList.Group, { title: "Available Tools", children: availableTools.map(tool => (_jsxs(ActionList.Item, { disabled: true, children: [_jsx(ActionList.LeadingVisual, { children: _jsx(Box, { sx: {
137
+ width: 8,
138
+ height: 8,
139
+ borderRadius: '50%',
140
+ backgroundColor: 'success.emphasis',
141
+ } }) }), tool.name] }, tool.id))) }) }) })] })), configQuery.data && model && (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Button, { type: "button", variant: "invisible", size: "small", leadingVisual: AiModelIcon, children: _jsx(Text, { sx: { fontSize: 0 }, children: configQuery.data.models.find(m => m.id === model)
142
+ ?.name || 'Select Model' }) }) }), _jsx(ActionMenu.Overlay, { children: _jsx(ActionList, { selectionVariant: "single", children: configQuery.data.models.map(modelItem => (_jsx(ActionList.Item, { selected: model === modelItem.id, onSelect: () => setModel(modelItem.id), children: modelItem.name }, modelItem.id))) }) })] }))] }), _jsx(Button, { type: "submit", variant: "primary", size: "small", disabled: !inputValue.trim() || status === 'streaming', leadingVisual: ArrowUpIcon, children: status === 'streaming' ? 'Sending...' : 'Send' })] })] }) })] }));
143
+ };
@@ -0,0 +1,11 @@
1
+ import type { UIDataTypes, UIMessagePart, UITools, UIMessage } from 'ai';
2
+ interface IMessagePartProps {
3
+ part: UIMessagePart<UIDataTypes, UITools>;
4
+ message: UIMessage;
5
+ status: string;
6
+ regen: (id: string) => void;
7
+ index: number;
8
+ lastMessage: boolean;
9
+ }
10
+ export declare function MessagePart({ part, message, status, regen, index, lastMessage, }: IMessagePartProps): import("react/jsx-runtime").JSX.Element | null;
11
+ export {};
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { TextPart } from './display/TextPart';
3
+ import { ReasoningPart } from './display/ReasoningPart';
4
+ import { ToolPart } from './display/ToolPart';
5
+ import { DynamicToolPart } from './display/DynamicToolPart';
6
+ export function MessagePart({ part, message, status, regen, index, lastMessage, }) {
7
+ if (part.type === 'text') {
8
+ return (_jsx(TextPart, { text: part.text, message: message, isLastPart: index === message.parts.length - 1, onRegenerate: regen }));
9
+ }
10
+ else if (part.type === 'reasoning') {
11
+ const isStreaming = status === 'streaming' &&
12
+ index === message.parts.length - 1 &&
13
+ lastMessage;
14
+ return _jsx(ReasoningPart, { text: part.text, isStreaming: isStreaming });
15
+ }
16
+ else if (part.type === 'dynamic-tool') {
17
+ return _jsx(DynamicToolPart, { part: part });
18
+ }
19
+ else if ('toolCallId' in part) {
20
+ return _jsx(ToolPart, { part: part });
21
+ }
22
+ return null;
23
+ }
@@ -0,0 +1,6 @@
1
+ import type { DynamicToolUIPart } from 'ai';
2
+ interface IDynamicToolPartProps {
3
+ part: DynamicToolUIPart;
4
+ }
5
+ export declare function DynamicToolPart({ part }: IDynamicToolPartProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,5 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text, Flash } from '@primer/react';
3
+ export function DynamicToolPart({ part }) {
4
+ return (_jsx(Flash, { variant: "warning", sx: { marginBottom: 2 }, children: _jsxs(Text, { children: ["Dynamic Tool: ", JSON.stringify(part)] }) }));
5
+ }
@@ -0,0 +1,6 @@
1
+ interface IReasoningPartProps {
2
+ text: string;
3
+ isStreaming: boolean;
4
+ }
5
+ export declare function ReasoningPart({ text, isStreaming }: IReasoningPartProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2023-2025 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /*
7
+ * Copyright (c) 2024-2025 Datalayer, Inc.
8
+ *
9
+ * BSD 3-Clause License
10
+ */
11
+ import React from 'react';
12
+ import { Text, Button } from '@primer/react';
13
+ import { Box } from '@datalayer/primer-addons';
14
+ import { ChevronDownIcon } from '@primer/octicons-react';
15
+ import { Streamdown } from 'streamdown';
16
+ export function ReasoningPart({ text, isStreaming }) {
17
+ const [isExpanded, setIsExpanded] = React.useState(false);
18
+ // Auto-close after streaming ends (with delay)
19
+ React.useEffect(() => {
20
+ if (!isStreaming && isExpanded) {
21
+ const timer = setTimeout(() => {
22
+ setIsExpanded(false);
23
+ }, 1000);
24
+ return () => clearTimeout(timer);
25
+ }
26
+ }, [isStreaming, isExpanded]);
27
+ return (_jsxs(Box, { sx: { marginBottom: 3 }, children: [_jsxs(Button, { variant: "invisible", size: "small", onClick: () => setIsExpanded(!isExpanded), sx: {
28
+ width: '100%',
29
+ display: 'flex',
30
+ gap: 2,
31
+ justifyContent: 'flex-start',
32
+ alignItems: 'center',
33
+ paddingX: 0,
34
+ paddingY: 1,
35
+ color: 'fg.muted',
36
+ border: 'none',
37
+ '&:hover': {
38
+ color: 'fg.default',
39
+ },
40
+ }, children: [_jsx(Text, { sx: { fontSize: 1 }, children: "\uD83E\uDDE0" }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'normal' }, children: isStreaming ? 'Thinking...' : 'Reasoning' }), _jsx(Box, { as: "span", sx: {
41
+ display: 'inline-flex',
42
+ marginLeft: 'auto',
43
+ transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',
44
+ transition: 'transform 0.2s',
45
+ }, children: _jsx(ChevronDownIcon, {}) })] }), isExpanded && (_jsx(Box, { sx: {
46
+ marginTop: 2,
47
+ padding: 3,
48
+ backgroundColor: 'canvas.inset',
49
+ borderRadius: 2,
50
+ border: '1px solid',
51
+ borderColor: 'border.default',
52
+ fontSize: 1,
53
+ lineHeight: 1.6,
54
+ color: 'fg.muted',
55
+ '& > *:first-child': { marginTop: 0 },
56
+ '& > *:last-child': { marginBottom: 0 },
57
+ }, children: _jsx(Streamdown, { children: text }) }))] }));
58
+ }
@@ -0,0 +1,9 @@
1
+ import type { UIMessage } from 'ai';
2
+ interface ITextPartProps {
3
+ text: string;
4
+ message: UIMessage;
5
+ isLastPart: boolean;
6
+ onRegenerate: (id: string) => void;
7
+ }
8
+ export declare function TextPart({ text, message, isLastPart, onRegenerate, }: ITextPartProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,93 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Text, IconButton } from '@primer/react';
3
+ import { Box } from '@datalayer/primer-addons';
4
+ import { CopyIcon, SyncIcon } from '@primer/octicons-react';
5
+ import { Streamdown } from 'streamdown';
6
+ export function TextPart({ text, message, isLastPart, onRegenerate, }) {
7
+ const copy = (text) => {
8
+ navigator.clipboard.writeText(text).catch((error) => {
9
+ console.error('Error copying text:', error);
10
+ });
11
+ };
12
+ return (_jsxs(Box, { sx: {
13
+ padding: 3,
14
+ borderRadius: 2,
15
+ backgroundColor: message.role === 'user' ? 'accent.subtle' : 'canvas.subtle',
16
+ marginBottom: 2,
17
+ }, children: [_jsxs(Box, { sx: {
18
+ display: 'flex',
19
+ justifyContent: 'space-between',
20
+ alignItems: 'flex-start',
21
+ marginBottom: 2,
22
+ }, children: [_jsx(Text, { sx: {
23
+ fontWeight: 'bold',
24
+ fontSize: 1,
25
+ color: 'fg.muted',
26
+ textTransform: 'uppercase',
27
+ }, children: message.role === 'user' ? 'You' : 'Assistant' }), message.role === 'assistant' && isLastPart && (_jsxs(Box, { sx: { display: 'flex', gap: 1 }, children: [_jsx(IconButton, { icon: SyncIcon, "aria-label": "Regenerate", size: "small", variant: "invisible", onClick: () => onRegenerate(message.id) }), _jsx(IconButton, { icon: CopyIcon, "aria-label": "Copy", size: "small", variant: "invisible", onClick: () => copy(text) })] }))] }), _jsx(Box, { sx: {
28
+ fontSize: 1,
29
+ lineHeight: 1.6,
30
+ '& > *:first-child': { marginTop: 0 },
31
+ '& > *:last-child': { marginBottom: 0 },
32
+ '& p': { marginTop: 0, marginBottom: '1em' },
33
+ '& h1, & h2, & h3, & h4, & h5, & h6': {
34
+ marginTop: '1em',
35
+ marginBottom: '0.5em',
36
+ fontWeight: 'bold',
37
+ },
38
+ '& ul, & ol': {
39
+ marginTop: '0.5em',
40
+ marginBottom: '0.5em',
41
+ paddingLeft: '1.5em',
42
+ },
43
+ '& code': {
44
+ backgroundColor: 'neutral.muted',
45
+ padding: '2px 4px',
46
+ borderRadius: 1,
47
+ fontSize: '0.9em',
48
+ fontFamily: 'mono',
49
+ },
50
+ '& pre': {
51
+ backgroundColor: 'canvas.inset',
52
+ padding: 3,
53
+ borderRadius: 2,
54
+ overflow: 'auto',
55
+ marginTop: '1em',
56
+ marginBottom: '1em',
57
+ border: '1px solid',
58
+ borderColor: 'border.default',
59
+ },
60
+ '& pre code': {
61
+ backgroundColor: 'transparent',
62
+ padding: 0,
63
+ fontSize: '0.875em',
64
+ },
65
+ '& blockquote': {
66
+ borderLeft: '3px solid',
67
+ borderColor: 'border.default',
68
+ paddingLeft: 3,
69
+ marginLeft: 0,
70
+ color: 'fg.muted',
71
+ },
72
+ '& a': {
73
+ color: 'accent.fg',
74
+ textDecoration: 'underline',
75
+ },
76
+ '& table': {
77
+ width: '100%',
78
+ borderCollapse: 'collapse',
79
+ marginTop: '1em',
80
+ marginBottom: '1em',
81
+ },
82
+ '& th, & td': {
83
+ border: '1px solid',
84
+ borderColor: 'border.default',
85
+ padding: 2,
86
+ textAlign: 'left',
87
+ },
88
+ '& th': {
89
+ backgroundColor: 'canvas.subtle',
90
+ fontWeight: 'bold',
91
+ },
92
+ }, children: _jsx(Streamdown, { children: text }) })] }));
93
+ }
@@ -0,0 +1,6 @@
1
+ import type { ToolUIPart } from 'ai';
2
+ interface IToolPartProps {
3
+ part: ToolUIPart;
4
+ }
5
+ export declare function ToolPart({ part }: IToolPartProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,148 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2023-2025 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /*
7
+ * Copyright (c) 2024-2025 Datalayer, Inc.
8
+ *
9
+ * BSD 3-Clause License
10
+ */
11
+ import React from 'react';
12
+ import { Text, Button } from '@primer/react';
13
+ import { Box } from '@datalayer/primer-addons';
14
+ import { ChevronDownIcon } from '@primer/octicons-react';
15
+ export function ToolPart({ part }) {
16
+ const [isExpanded, setIsExpanded] = React.useState(true);
17
+ const getStatusInfo = (state) => {
18
+ const statusMap = {
19
+ call: { label: 'Pending', color: 'accent.fg', icon: '○' },
20
+ 'input-streaming': { label: 'Pending', color: 'accent.fg', icon: '○' },
21
+ 'input-available': {
22
+ label: 'Running',
23
+ color: 'attention.fg',
24
+ icon: '⏱',
25
+ },
26
+ executing: { label: 'Running', color: 'attention.fg', icon: '⏱' },
27
+ 'output-available': {
28
+ label: 'Completed',
29
+ color: 'success.fg',
30
+ icon: '✓',
31
+ },
32
+ 'output-error': { label: 'Error', color: 'danger.fg', icon: '✕' },
33
+ error: { label: 'Error', color: 'danger.fg', icon: '✕' },
34
+ };
35
+ return (statusMap[state] || {
36
+ label: state,
37
+ color: 'fg.muted',
38
+ icon: '•',
39
+ });
40
+ };
41
+ const statusInfo = getStatusInfo(part.state);
42
+ const toolName = part.type.split('-').slice(1).join('-') || part.type;
43
+ return (_jsxs(Box, { sx: {
44
+ marginBottom: 2,
45
+ border: '1px solid',
46
+ borderColor: 'border.default',
47
+ borderRadius: 2,
48
+ overflow: 'hidden',
49
+ }, children: [_jsxs(Button, { variant: "invisible", onClick: () => setIsExpanded(!isExpanded), sx: {
50
+ width: '100%',
51
+ display: 'flex',
52
+ justifyContent: 'space-between',
53
+ alignItems: 'center',
54
+ padding: 3,
55
+ backgroundColor: 'canvas.subtle',
56
+ border: 'none',
57
+ borderBottom: isExpanded ? '1px solid' : 'none',
58
+ borderColor: 'border.default',
59
+ textAlign: 'left',
60
+ cursor: 'pointer',
61
+ '&:hover': {
62
+ backgroundColor: 'neutral.muted',
63
+ },
64
+ }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "\uD83D\uDD27" }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: toolName }), _jsxs(Box, { sx: {
65
+ display: 'inline-flex',
66
+ alignItems: 'center',
67
+ gap: 1,
68
+ paddingX: 2,
69
+ paddingY: 1,
70
+ borderRadius: 2,
71
+ backgroundColor: 'neutral.subtle',
72
+ fontSize: 0,
73
+ }, children: [_jsx(Text, { sx: { color: statusInfo.color }, children: statusInfo.icon }), _jsx(Text, { sx: { color: statusInfo.color, fontWeight: 'semibold' }, children: statusInfo.label })] })] }), _jsx(Box, { as: "span", sx: {
74
+ display: 'inline-flex',
75
+ transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',
76
+ transition: 'transform 0.2s',
77
+ }, children: _jsx(ChevronDownIcon, {}) })] }), isExpanded && (_jsxs(Box, { children: [_jsxs(Box, { sx: {
78
+ padding: 3,
79
+ borderBottom: part.state === 'output-available' ||
80
+ part.state === 'output-error'
81
+ ? '1px solid'
82
+ : 'none',
83
+ borderColor: 'border.default',
84
+ }, children: [_jsx(Text, { sx: {
85
+ display: 'block',
86
+ fontSize: 0,
87
+ fontWeight: 'semibold',
88
+ color: 'fg.muted',
89
+ textTransform: 'uppercase',
90
+ letterSpacing: '0.05em',
91
+ marginBottom: 2,
92
+ }, children: "Parameters" }), _jsx(Box, { sx: {
93
+ backgroundColor: 'canvas.inset',
94
+ borderRadius: 2,
95
+ overflow: 'auto',
96
+ border: '1px solid',
97
+ borderColor: 'border.default',
98
+ }, children: _jsx("pre", { style: {
99
+ margin: 0,
100
+ padding: '12px',
101
+ fontSize: '12px',
102
+ fontFamily: 'monospace',
103
+ lineHeight: 1.5,
104
+ overflow: 'auto',
105
+ }, children: JSON.stringify(part.input, null, 2) }) })] }), part.state === 'output-available' && (_jsxs(Box, { sx: { padding: 3 }, children: [_jsx(Text, { sx: {
106
+ display: 'block',
107
+ fontSize: 0,
108
+ fontWeight: 'semibold',
109
+ color: 'fg.muted',
110
+ textTransform: 'uppercase',
111
+ letterSpacing: '0.05em',
112
+ marginBottom: 2,
113
+ }, children: "Result" }), _jsx(Box, { sx: {
114
+ backgroundColor: 'canvas.default',
115
+ borderRadius: 2,
116
+ overflow: 'auto',
117
+ border: '1px solid',
118
+ borderColor: 'border.default',
119
+ }, children: _jsx("pre", { style: {
120
+ margin: 0,
121
+ padding: '12px',
122
+ fontSize: '12px',
123
+ fontFamily: 'monospace',
124
+ lineHeight: 1.5,
125
+ overflow: 'auto',
126
+ }, children: part.output
127
+ ? typeof part.output === 'string'
128
+ ? part.output
129
+ : JSON.stringify(part.output, null, 2)
130
+ : 'No output' }) })] })), part.state === 'output-error' &&
131
+ 'errorText' in part &&
132
+ part.errorText && (_jsxs(Box, { sx: { padding: 3 }, children: [_jsx(Text, { sx: {
133
+ display: 'block',
134
+ fontSize: 0,
135
+ fontWeight: 'semibold',
136
+ color: 'danger.fg',
137
+ textTransform: 'uppercase',
138
+ letterSpacing: '0.05em',
139
+ marginBottom: 2,
140
+ }, children: "Error" }), _jsx(Box, { sx: {
141
+ backgroundColor: 'danger.subtle',
142
+ borderRadius: 2,
143
+ overflow: 'auto',
144
+ border: '1px solid',
145
+ borderColor: 'danger.muted',
146
+ padding: 2,
147
+ }, children: _jsx(Text, { sx: { fontSize: 0, color: 'danger.fg' }, children: part.errorText }) })] }))] }))] }));
148
+ }
@@ -0,0 +1,4 @@
1
+ export { TextPart } from './TextPart';
2
+ export { ReasoningPart } from './ReasoningPart';
3
+ export { ToolPart } from './ToolPart';
4
+ export { DynamicToolPart } from './DynamicToolPart';
@@ -0,0 +1,13 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /*
6
+ * Copyright (c) 2024-2025 Datalayer, Inc.
7
+ *
8
+ * BSD 3-Clause License
9
+ */
10
+ export { TextPart } from './TextPart';
11
+ export { ReasoningPart } from './ReasoningPart';
12
+ export { ToolPart } from './ToolPart';
13
+ export { DynamicToolPart } from './DynamicToolPart';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Call the API extension
3
+ *
4
+ * @param endPoint API REST end point for the extension
5
+ * @param init Initial values for the request
6
+ * @returns The response body interpreted as JSON
7
+ */
8
+ export declare function requestAPI<T>(endPoint?: string, init?: RequestInit): Promise<T>;
@@ -0,0 +1,43 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /*
6
+ * Copyright (c) 2024-2025 Datalayer, Inc.
7
+ *
8
+ * BSD 3-Clause License
9
+ */
10
+ import { URLExt } from '@jupyterlab/coreutils';
11
+ import { ServerConnection } from '@jupyterlab/services';
12
+ /**
13
+ * Call the API extension
14
+ *
15
+ * @param endPoint API REST end point for the extension
16
+ * @param init Initial values for the request
17
+ * @returns The response body interpreted as JSON
18
+ */
19
+ export async function requestAPI(endPoint = '', init = {}) {
20
+ // Make request to Jupyter API
21
+ const settings = ServerConnection.makeSettings();
22
+ const requestUrl = URLExt.join(settings.baseUrl, 'datalayer', endPoint);
23
+ let response;
24
+ try {
25
+ response = await ServerConnection.makeRequest(requestUrl, init, settings);
26
+ }
27
+ catch (error) {
28
+ throw new ServerConnection.NetworkError(error);
29
+ }
30
+ let data = await response.text();
31
+ if (data.length > 0) {
32
+ try {
33
+ data = JSON.parse(data);
34
+ }
35
+ catch {
36
+ // Not a JSON response body
37
+ }
38
+ }
39
+ if (!response.ok) {
40
+ throw new ServerConnection.ResponseError(response, data.message || data);
41
+ }
42
+ return data;
43
+ }
@@ -0,0 +1,4 @@
1
+ export * from './ChatComponent';
2
+ export * from './MessagePart';
3
+ export * from './handler';
4
+ export * from './display';
@@ -0,0 +1,13 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /*
6
+ * Copyright (c) 2024-2025 Datalayer, Inc.
7
+ *
8
+ * BSD 3-Clause License
9
+ */
10
+ export * from './ChatComponent';
11
+ export * from './MessagePart';
12
+ export * from './handler';
13
+ export * from './display';
@@ -7,8 +7,5 @@ type ICenteredSpinnerProps = {
7
7
  message?: string;
8
8
  size?: keyof typeof sizeMap;
9
9
  };
10
- export declare const CenteredSpinner: {
11
- (props: ICenteredSpinnerProps): import("react/jsx-runtime").JSX.Element;
12
- defaultProps: Partial<ICenteredSpinnerProps>;
13
- };
10
+ export declare const CenteredSpinner: ({ message, size, }: ICenteredSpinnerProps) => import("react/jsx-runtime").JSX.Element;
14
11
  export default CenteredSpinner;
@@ -5,8 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  */
6
6
  import { Spinner, Text } from '@primer/react';
7
7
  import { Box } from '@datalayer/primer-addons';
8
- export const CenteredSpinner = (props) => {
9
- const { message, size } = props;
8
+ export const CenteredSpinner = ({ message, size = 'medium', }) => {
10
9
  return (_jsxs(Box, { sx: {
11
10
  display: 'flex',
12
11
  alignItems: 'center',
@@ -14,7 +13,4 @@ export const CenteredSpinner = (props) => {
14
13
  minHeight: '40px',
15
14
  }, children: [_jsx(Spinner, { size: size }), message && _jsx(Text, { sx: { marginLeft: 3 }, children: message })] }));
16
15
  };
17
- CenteredSpinner.defaultProps = {
18
- size: 'medium',
19
- };
20
16
  export default CenteredSpinner;