@datalayer/agent-runtimes 0.0.11 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/Agent.d.ts +29 -0
- package/lib/Agent.js +131 -0
- package/lib/AgentLexical.d.ts +33 -0
- package/lib/AgentLexical.js +295 -0
- package/lib/AgentNotebook.d.ts +19 -0
- package/lib/AgentNotebook.js +192 -0
- package/lib/agent-lexical-main.d.ts +1 -0
- package/lib/agent-lexical-main.js +11 -0
- package/lib/agent-main.d.ts +1 -0
- package/lib/agent-main.js +11 -0
- package/lib/agent-notebook-main.d.ts +1 -0
- package/lib/agent-notebook-main.js +12 -0
- package/lib/components/AgentConfiguration.d.ts +4 -22
- package/lib/components/AgentConfiguration.js +8 -8
- package/lib/components/chat/components/AgentDetails.d.ts +3 -1
- package/lib/components/chat/components/AgentDetails.js +6 -6
- package/lib/components/chat/components/Chat.d.ts +29 -3
- package/lib/components/chat/components/Chat.js +64 -59
- package/lib/components/chat/components/ChatFloating.d.ts +34 -12
- package/lib/components/chat/components/ChatFloating.js +54 -21
- package/lib/components/chat/components/ChatInline.d.ts +5 -1
- package/lib/components/chat/components/ChatInline.js +8 -1
- package/lib/components/chat/components/ChatSidebar.d.ts +6 -1
- package/lib/components/chat/components/ChatSidebar.js +2 -2
- package/lib/components/chat/components/ChatStandalone.d.ts +6 -1
- package/lib/components/chat/components/ChatStandalone.js +2 -2
- package/lib/components/chat/components/base/ChatBase.d.ts +49 -8
- package/lib/components/chat/components/base/ChatBase.js +544 -149
- package/lib/components/chat/components/base/InputPrompt.d.ts +42 -0
- package/lib/components/chat/components/base/InputPrompt.js +131 -0
- package/lib/components/chat/components/index.d.ts +3 -3
- package/lib/components/chat/components/index.js +1 -1
- package/lib/components/chat/components/parts/ReasoningPart.js +2 -4
- package/lib/components/chat/components/parts/TextPart.js +2 -70
- package/lib/components/chat/components/styles/streamdownStyles.d.ts +23 -0
- package/lib/components/chat/components/styles/streamdownStyles.js +319 -0
- package/lib/components/chat/index.d.ts +1 -1
- package/lib/components/chat/index.js +1 -1
- package/lib/components/chat/inference/DatalayerInferenceProvider.js +16 -12
- package/lib/components/chat/inference/SelfHostedInferenceProvider.js +16 -12
- package/lib/components/chat/protocols/AGUIAdapter.d.ts +10 -3
- package/lib/components/chat/protocols/AGUIAdapter.js +123 -44
- package/lib/components/chat/types/tool.d.ts +5 -2
- package/lib/components/index.d.ts +1 -18
- package/lib/components/index.js +0 -9
- package/lib/config/index.d.ts +0 -4
- package/lib/config/index.js +0 -4
- package/lib/examples/A2UiRestaurantExample.js +1 -1
- package/lib/examples/AgentRuntimeChatExample.d.ts +15 -0
- package/lib/examples/AgentRuntimeChatExample.js +126 -0
- package/lib/examples/{AgentSpaceFormExample.d.ts → AgentRuntimeFormExample.d.ts} +3 -3
- package/lib/examples/{AgentSpaceFormExample.js → AgentRuntimeFormExample.js} +10 -8
- package/lib/examples/AgentRuntimeLexical2Example.d.ts +0 -1
- package/lib/examples/AgentRuntimeLexical2Example.js +0 -1
- package/lib/examples/AgentRuntimeLexicalExample.d.ts +0 -1
- package/lib/examples/AgentRuntimeLexicalExample.js +6 -4
- package/lib/examples/AgentRuntimeLexicalSidebarExample.d.ts +0 -1
- package/lib/examples/AgentRuntimeLexicalSidebarExample.js +8 -2
- package/lib/examples/AgentRuntimeNotebookExample.js +6 -5
- package/lib/examples/CopilotKitLexicalExample.d.ts +0 -1
- package/lib/examples/CopilotKitLexicalExample.js +0 -1
- package/lib/examples/CopilotKitNotebookExample.js +2 -2
- package/lib/examples/JupyterNotebookExample.js +2 -2
- package/lib/{components → examples/components}/Header.d.ts +2 -1
- package/lib/{components → examples/components}/HeaderControls.js +1 -1
- package/lib/{components → examples/components}/LexicalEditor.d.ts +6 -1
- package/lib/{components → examples/components}/LexicalEditor.js +4 -4
- package/lib/{components → examples/components}/MainContent.d.ts +1 -1
- package/lib/{components → examples/components}/MainContent.js +7 -5
- package/lib/examples/components/index.d.ts +16 -0
- package/lib/examples/components/index.js +13 -0
- package/lib/examples/example-selector.js +2 -1
- package/lib/examples/index.d.ts +1 -1
- package/lib/examples/index.js +1 -1
- package/lib/examples/main.js +2 -2
- package/lib/examples/stores/examplesStore.d.ts +2 -23
- package/lib/index.d.ts +2 -1
- package/lib/index.js +1 -0
- package/lib/lexical/ChatInlinePlugin.d.ts +13 -2
- package/lib/lexical/ChatInlinePlugin.js +66 -183
- package/lib/lexical/index.d.ts +1 -0
- package/lib/lexical/index.js +1 -0
- package/lib/lexical/useChatInlineToolbarItems.d.ts +35 -0
- package/lib/lexical/useChatInlineToolbarItems.js +91 -0
- package/lib/runtime/useAgentRuntime.d.ts +1 -1
- package/lib/runtime/useAgentRuntime.js +1 -1
- package/lib/{config/agents/code-ai → specs/agents/codeai}/agents.d.ts +5 -2
- package/lib/specs/agents/codeai/agents.js +151 -0
- package/lib/{config → specs}/agents/codemode-paper/agents.d.ts +4 -2
- package/lib/{config → specs}/agents/codemode-paper/agents.js +39 -19
- package/lib/{config → specs}/agents/datalayer-ai/agents.d.ts +4 -2
- package/lib/{config → specs}/agents/datalayer-ai/agents.js +17 -2
- package/lib/{config → specs}/agents/index.d.ts +3 -1
- package/lib/{config → specs}/agents/index.js +12 -3
- package/lib/{config → specs}/envvars.d.ts +1 -0
- package/lib/{config → specs}/envvars.js +10 -0
- package/lib/specs/index.d.ts +5 -0
- package/lib/specs/index.js +9 -0
- package/lib/{config → specs}/mcpServers.d.ts +2 -1
- package/lib/{config → specs}/mcpServers.js +23 -1
- package/lib/specs/models.d.ts +68 -0
- package/lib/specs/models.js +239 -0
- package/lib/state/substates/AIAgentState.d.ts +0 -1
- package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.d.ts +11 -22
- package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.js +5 -5
- package/lib/tools/adapters/agent-runtimes/lexicalHooks.d.ts +6 -6
- package/lib/tools/adapters/agent-runtimes/lexicalHooks.js +4 -4
- package/lib/tools/adapters/agent-runtimes/notebookHooks.d.ts +6 -6
- package/lib/tools/adapters/agent-runtimes/notebookHooks.js +4 -4
- package/lib/{types.d.ts → types/Types.d.ts} +32 -6
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +1 -0
- package/package.json +11 -5
- package/scripts/codegen/generate_agents.py +53 -13
- package/scripts/codegen/generate_envvars.py +1 -1
- package/scripts/codegen/generate_mcp_servers.py +5 -5
- package/scripts/codegen/generate_models.py +486 -0
- package/scripts/codegen/generate_skills.py +2 -2
- package/style/primer-primitives.css +22 -0
- package/lib/components/chat/components/elements/ChatInputPrompt.d.ts +0 -37
- package/lib/components/chat/components/elements/ChatInputPrompt.js +0 -150
- package/lib/config/agents/code-ai/agents.js +0 -70
- /package/lib/{components → examples/components}/FooterMetrics.d.ts +0 -0
- /package/lib/{components → examples/components}/FooterMetrics.js +0 -0
- /package/lib/{components → examples/components}/Header.js +0 -0
- /package/lib/{components → examples/components}/HeaderControls.d.ts +0 -0
- /package/lib/{components → examples/components}/MockFileBrowser.d.ts +0 -0
- /package/lib/{components → examples/components}/MockFileBrowser.js +0 -0
- /package/lib/{components → examples/components}/SessionTabs.d.ts +0 -0
- /package/lib/{components → examples/components}/SessionTabs.js +0 -0
- /package/lib/{components → examples/components}/TimeTravel.d.ts +0 -0
- /package/lib/{components → examples/components}/TimeTravel.js +0 -0
- /package/lib/{config/agents/code-ai → specs/agents/codeai}/index.d.ts +0 -0
- /package/lib/{config/agents/code-ai → specs/agents/codeai}/index.js +0 -0
- /package/lib/{config → specs}/agents/codemode-paper/index.d.ts +0 -0
- /package/lib/{config → specs}/agents/codemode-paper/index.js +0 -0
- /package/lib/{config → specs}/agents/datalayer-ai/index.d.ts +0 -0
- /package/lib/{config → specs}/agents/datalayer-ai/index.js +0 -0
- /package/lib/{config → specs}/skills.d.ts +0 -0
- /package/lib/{config → specs}/skills.js +0 -0
- /package/lib/{types.js → types/Types.js} +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Props for the InputPrompt component.
|
|
3
|
+
*/
|
|
4
|
+
export interface InputPromptProps {
|
|
5
|
+
/** Placeholder text for the textarea */
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
/** Whether the input is in a loading/sending state */
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
/** Callback when a message is submitted */
|
|
10
|
+
onSend: (message: string) => void;
|
|
11
|
+
/** Callback when the stop button is clicked */
|
|
12
|
+
onStop?: () => void;
|
|
13
|
+
/** Auto-focus the input on mount */
|
|
14
|
+
autoFocus?: boolean;
|
|
15
|
+
/** Trigger value change to refocus input */
|
|
16
|
+
focusTrigger?: number;
|
|
17
|
+
/** Whether to show a border on top */
|
|
18
|
+
showBorderTop?: boolean;
|
|
19
|
+
/** Whether to use subtle background */
|
|
20
|
+
showBackground?: boolean;
|
|
21
|
+
/** Custom padding (default: 3) */
|
|
22
|
+
padding?: number;
|
|
23
|
+
/** Whether the prompt is disabled */
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
/** Additional sx props for the outer container */
|
|
26
|
+
sx?: Record<string, unknown>;
|
|
27
|
+
/** Controlled input value (external state) */
|
|
28
|
+
value?: string;
|
|
29
|
+
/** Controlled input onChange (external state) */
|
|
30
|
+
onChange?: (value: string) => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* InputPrompt — A standalone chat input with send button.
|
|
34
|
+
*
|
|
35
|
+
* Features:
|
|
36
|
+
* - Auto-resizing textarea (min 40px, max 120px)
|
|
37
|
+
* - Enter to send, Shift+Enter for newline
|
|
38
|
+
* - Send / Stop toggle based on loading state
|
|
39
|
+
* - Auto-focus support
|
|
40
|
+
*/
|
|
41
|
+
export declare function InputPrompt({ placeholder, isLoading, onSend, onStop, autoFocus, focusTrigger, showBorderTop, showBackground, padding, disabled, sx, value: controlledValue, onChange: controlledOnChange, }: InputPromptProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
export default InputPrompt;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* InputPrompt - Standalone input prompt component extracted from ChatBase.
|
|
8
|
+
*
|
|
9
|
+
* Provides a textarea with a send/stop button, auto-resize behavior,
|
|
10
|
+
* and keyboard shortcuts (Enter to send, Shift+Enter for newline).
|
|
11
|
+
*
|
|
12
|
+
* Can be used independently of ChatBase for embedding a prompt input
|
|
13
|
+
* in any context (e.g. landing pages, home screens).
|
|
14
|
+
*
|
|
15
|
+
* @module components/chat/components/base/InputPrompt
|
|
16
|
+
*/
|
|
17
|
+
import { useCallback, useEffect, useRef, useState, } from 'react';
|
|
18
|
+
import { Textarea, IconButton } from '@primer/react';
|
|
19
|
+
import { Box } from '@datalayer/primer-addons';
|
|
20
|
+
import { PaperAirplaneIcon, SquareCircleIcon } from '@primer/octicons-react';
|
|
21
|
+
/**
|
|
22
|
+
* InputPrompt — A standalone chat input with send button.
|
|
23
|
+
*
|
|
24
|
+
* Features:
|
|
25
|
+
* - Auto-resizing textarea (min 40px, max 120px)
|
|
26
|
+
* - Enter to send, Shift+Enter for newline
|
|
27
|
+
* - Send / Stop toggle based on loading state
|
|
28
|
+
* - Auto-focus support
|
|
29
|
+
*/
|
|
30
|
+
export function InputPrompt({ placeholder = 'Type a message...', isLoading = false, onSend, onStop, autoFocus = false, focusTrigger, showBorderTop = true, showBackground = true, padding = 3, disabled = false, sx, value: controlledValue, onChange: controlledOnChange, }) {
|
|
31
|
+
// Internal state (used when not controlled)
|
|
32
|
+
const [internalInput, setInternalInput] = useState('');
|
|
33
|
+
const input = controlledValue !== undefined ? controlledValue : internalInput;
|
|
34
|
+
const setInput = controlledOnChange !== undefined ? controlledOnChange : setInternalInput;
|
|
35
|
+
const inputRef = useRef(null);
|
|
36
|
+
// Auto-focus on mount
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (autoFocus && inputRef.current) {
|
|
39
|
+
const timeoutId = setTimeout(() => {
|
|
40
|
+
inputRef.current?.focus();
|
|
41
|
+
}, 100);
|
|
42
|
+
return () => clearTimeout(timeoutId);
|
|
43
|
+
}
|
|
44
|
+
}, [autoFocus]);
|
|
45
|
+
// Refocus when focusTrigger changes
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (focusTrigger !== undefined && focusTrigger > 0 && inputRef.current) {
|
|
48
|
+
const timeoutId = setTimeout(() => {
|
|
49
|
+
inputRef.current?.focus();
|
|
50
|
+
}, 150);
|
|
51
|
+
return () => clearTimeout(timeoutId);
|
|
52
|
+
}
|
|
53
|
+
}, [focusTrigger]);
|
|
54
|
+
// Track previous loading state to detect when loading completes
|
|
55
|
+
const wasLoadingRef = useRef(false);
|
|
56
|
+
// Refocus input when loading completes
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (wasLoadingRef.current && !isLoading && inputRef.current) {
|
|
59
|
+
const timeoutId = setTimeout(() => {
|
|
60
|
+
inputRef.current?.focus();
|
|
61
|
+
}, 50);
|
|
62
|
+
return () => clearTimeout(timeoutId);
|
|
63
|
+
}
|
|
64
|
+
wasLoadingRef.current = isLoading;
|
|
65
|
+
}, [isLoading]);
|
|
66
|
+
// Auto-resize textarea based on content
|
|
67
|
+
const adjustTextareaHeight = useCallback(() => {
|
|
68
|
+
const textarea = inputRef.current;
|
|
69
|
+
if (textarea) {
|
|
70
|
+
textarea.style.height = 'auto';
|
|
71
|
+
const maxHeight = 120;
|
|
72
|
+
const minHeight = 40;
|
|
73
|
+
const newHeight = Math.min(Math.max(textarea.scrollHeight, minHeight), maxHeight);
|
|
74
|
+
textarea.style.height = `${newHeight}px`;
|
|
75
|
+
textarea.style.overflowY =
|
|
76
|
+
textarea.scrollHeight > maxHeight ? 'auto' : 'hidden';
|
|
77
|
+
}
|
|
78
|
+
}, []);
|
|
79
|
+
// Adjust textarea height when input changes
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
adjustTextareaHeight();
|
|
82
|
+
}, [input, adjustTextareaHeight]);
|
|
83
|
+
// Ensure textarea has a minimum height on mount
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const timer = setTimeout(adjustTextareaHeight, 0);
|
|
86
|
+
return () => clearTimeout(timer);
|
|
87
|
+
}, [adjustTextareaHeight]);
|
|
88
|
+
// Send handler
|
|
89
|
+
const handleSend = useCallback(() => {
|
|
90
|
+
if (!input.trim() || isLoading || disabled)
|
|
91
|
+
return;
|
|
92
|
+
const message = input.trim();
|
|
93
|
+
// Only clear input if not controlled externally
|
|
94
|
+
if (controlledValue === undefined) {
|
|
95
|
+
setInput('');
|
|
96
|
+
}
|
|
97
|
+
onSend(message);
|
|
98
|
+
}, [input, isLoading, disabled, onSend, setInput, controlledValue]);
|
|
99
|
+
// Stop handler
|
|
100
|
+
const handleStop = useCallback(() => {
|
|
101
|
+
onStop?.();
|
|
102
|
+
}, [onStop]);
|
|
103
|
+
// Keyboard handler
|
|
104
|
+
const handleKeyDown = useCallback((e) => {
|
|
105
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
handleSend();
|
|
108
|
+
}
|
|
109
|
+
}, [handleSend]);
|
|
110
|
+
return (_jsx(Box, { sx: sx, children: _jsx(Box, { sx: {
|
|
111
|
+
p: padding,
|
|
112
|
+
...(showBorderTop && {
|
|
113
|
+
borderTop: '1px solid',
|
|
114
|
+
borderColor: 'border.default',
|
|
115
|
+
}),
|
|
116
|
+
...(showBackground && {
|
|
117
|
+
bg: 'canvas.subtle',
|
|
118
|
+
}),
|
|
119
|
+
}, children: _jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'flex-end' }, children: [_jsx(Textarea, { ref: inputRef, value: input, onChange: e => {
|
|
120
|
+
setInput(e.target.value);
|
|
121
|
+
}, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: isLoading || disabled, sx: {
|
|
122
|
+
flex: 1,
|
|
123
|
+
resize: 'none',
|
|
124
|
+
minHeight: '40px',
|
|
125
|
+
maxHeight: '120px',
|
|
126
|
+
overflow: 'hidden',
|
|
127
|
+
transition: 'height 0.1s ease-out',
|
|
128
|
+
py: '2px',
|
|
129
|
+
}, rows: 1 }), isLoading ? (_jsx(IconButton, { icon: SquareCircleIcon, "aria-label": "Stop", onClick: handleStop, sx: { alignSelf: 'flex-end' } })) : (_jsx(IconButton, { icon: PaperAirplaneIcon, "aria-label": "Send", onClick: handleSend, disabled: !input.trim() || disabled, sx: { alignSelf: 'flex-end' } }))] }) }) }));
|
|
130
|
+
}
|
|
131
|
+
export default InputPrompt;
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* @module components/chat/components
|
|
5
5
|
*/
|
|
6
6
|
export { ChatMessages, type ChatMessagesProps } from './elements/ChatMessages';
|
|
7
|
-
export { ChatInputPrompt, type ChatInputPromptProps, } from './elements/ChatInputPrompt';
|
|
8
7
|
export { ChatSidebar, type ChatSidebarProps } from './ChatSidebar';
|
|
9
8
|
export { ChatStandalone, type ChatStandaloneProps, type MessageHandler, } from './ChatStandalone';
|
|
10
|
-
export { ChatBase, type ChatBaseProps, type ProtocolConfig, type AgentRuntimeConfig, type AvatarConfig, type EmptyStateConfig, type HeaderButtonsConfig, type StreamingMessageOptions, } from './base/ChatBase';
|
|
9
|
+
export { ChatBase, type ChatBaseProps, type ProtocolConfig, type AgentRuntimeConfig, type AvatarConfig, type EmptyStateConfig, type HeaderButtonsConfig, type StreamingMessageOptions, type ChatViewMode, } from './base/ChatBase';
|
|
10
|
+
export { InputPrompt, type InputPromptProps } from './base/InputPrompt';
|
|
11
11
|
export { AgentDetails, type AgentDetailsProps } from './AgentDetails';
|
|
12
12
|
export { AgentIdentity, IdentityCard, getTokenStatus, formatDuration, formatExpirationStatus, type AgentIdentityProps, type IdentityCardProps, type TokenStatus, } from './AgentIdentity';
|
|
13
13
|
export { ContextUsage, type ContextUsageProps, type ContextDetailsResponse, } from './ContextUsage';
|
|
@@ -22,5 +22,5 @@ export { MessagePart, type MessagePartProps } from './elements/MessagePart';
|
|
|
22
22
|
export { TextPart, type TextPartProps, ReasoningPart, type ReasoningPartProps, ToolPart, type ToolPartProps, DynamicToolPart, type DynamicToolPartProps, } from './parts';
|
|
23
23
|
export { ToolCallDisplay, type ToolCallDisplayProps } from './display';
|
|
24
24
|
export { Chat, type ChatProps, type Transport, type Extension } from './Chat';
|
|
25
|
-
export { ChatFloating, type ChatFloatingProps, type ToolCallRenderContext, type ToolCallStatus, type RenderToolResult, type RespondCallback, type Suggestion, type RemoteConfig, type ModelConfig, type BuiltinTool, type MCPServerConfig, type MCPServerTool, } from './ChatFloating';
|
|
25
|
+
export { ChatFloating, type ChatFloatingProps, type ToolCallRenderContext, type ToolCallStatus, type RenderToolResult, type RespondCallback, type Suggestion, type RemoteConfig, type ModelConfig, type BuiltinTool, type MCPServerConfig, type MCPServerTool, type ChatViewMode as ChatFloatingViewMode, } from './ChatFloating';
|
|
26
26
|
export { ChatInline, type ChatInlineProps, type ChatInlineProtocolConfig, } from './ChatInline';
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
* @module components/chat/components
|
|
9
9
|
*/
|
|
10
10
|
export { ChatMessages } from './elements/ChatMessages';
|
|
11
|
-
export { ChatInputPrompt, } from './elements/ChatInputPrompt';
|
|
12
11
|
export { ChatSidebar } from './ChatSidebar';
|
|
13
12
|
export { ChatStandalone, } from './ChatStandalone';
|
|
14
13
|
export { ChatBase, } from './base/ChatBase';
|
|
14
|
+
export { InputPrompt } from './base/InputPrompt';
|
|
15
15
|
export { AgentDetails } from './AgentDetails';
|
|
16
16
|
export { AgentIdentity, IdentityCard, getTokenStatus, formatDuration, formatExpirationStatus, } from './AgentIdentity';
|
|
17
17
|
export { ContextUsage, } from './ContextUsage';
|
|
@@ -14,6 +14,7 @@ import { Text, Button } from '@primer/react';
|
|
|
14
14
|
import { Box } from '@datalayer/primer-addons';
|
|
15
15
|
import { ChevronDownIcon } from '@primer/octicons-react';
|
|
16
16
|
import { Streamdown } from 'streamdown';
|
|
17
|
+
import { streamdownMarkdownStyles } from '../styles/streamdownStyles';
|
|
17
18
|
/**
|
|
18
19
|
* ReasoningPart component for displaying AI reasoning/thinking.
|
|
19
20
|
*
|
|
@@ -59,11 +60,8 @@ export function ReasoningPart({ text, isStreaming }) {
|
|
|
59
60
|
borderRadius: 2,
|
|
60
61
|
border: '1px solid',
|
|
61
62
|
borderColor: 'border.default',
|
|
62
|
-
fontSize: 1,
|
|
63
|
-
lineHeight: 1.6,
|
|
64
63
|
color: 'fg.muted',
|
|
65
|
-
|
|
66
|
-
'& > *:last-child': { marginBottom: 0 },
|
|
64
|
+
...streamdownMarkdownStyles,
|
|
67
65
|
}, children: _jsx(Streamdown, { children: text }) }))] }));
|
|
68
66
|
}
|
|
69
67
|
export default ReasoningPart;
|
|
@@ -3,6 +3,7 @@ import { Text, IconButton } from '@primer/react';
|
|
|
3
3
|
import { Box } from '@datalayer/primer-addons';
|
|
4
4
|
import { CopyIcon, SyncIcon } from '@primer/octicons-react';
|
|
5
5
|
import { Streamdown } from 'streamdown';
|
|
6
|
+
import { streamdownMarkdownStyles } from '../styles/streamdownStyles';
|
|
6
7
|
/**
|
|
7
8
|
* TextPart component for rendering text content with markdown support.
|
|
8
9
|
*
|
|
@@ -33,75 +34,6 @@ export function TextPart({ text, message, isLastPart, onRegenerate, }) {
|
|
|
33
34
|
fontSize: 1,
|
|
34
35
|
color: 'fg.muted',
|
|
35
36
|
textTransform: 'uppercase',
|
|
36
|
-
}, 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: {
|
|
37
|
-
fontSize: 1,
|
|
38
|
-
lineHeight: 1.6,
|
|
39
|
-
'& > *:first-child': { marginTop: 0 },
|
|
40
|
-
'& > *:last-child': { marginBottom: 0 },
|
|
41
|
-
'& p': { marginTop: 0, marginBottom: '1em' },
|
|
42
|
-
'& h1, & h2, & h3, & h4, & h5, & h6': {
|
|
43
|
-
marginTop: '1em',
|
|
44
|
-
marginBottom: '0.5em',
|
|
45
|
-
fontWeight: 'bold',
|
|
46
|
-
},
|
|
47
|
-
'& ul, & ol': {
|
|
48
|
-
marginTop: '0.5em',
|
|
49
|
-
marginBottom: '0.5em',
|
|
50
|
-
paddingLeft: '1.2em',
|
|
51
|
-
marginLeft: '0.3em',
|
|
52
|
-
},
|
|
53
|
-
'& li': {
|
|
54
|
-
listStylePosition: 'inside',
|
|
55
|
-
},
|
|
56
|
-
'& code': {
|
|
57
|
-
backgroundColor: 'neutral.muted',
|
|
58
|
-
padding: '2px 4px',
|
|
59
|
-
borderRadius: 1,
|
|
60
|
-
fontSize: '0.9em',
|
|
61
|
-
fontFamily: 'mono',
|
|
62
|
-
},
|
|
63
|
-
'& pre': {
|
|
64
|
-
backgroundColor: 'canvas.inset',
|
|
65
|
-
padding: 3,
|
|
66
|
-
borderRadius: 2,
|
|
67
|
-
overflow: 'auto',
|
|
68
|
-
marginTop: '1em',
|
|
69
|
-
marginBottom: '1em',
|
|
70
|
-
border: '1px solid',
|
|
71
|
-
borderColor: 'border.default',
|
|
72
|
-
},
|
|
73
|
-
'& pre code': {
|
|
74
|
-
backgroundColor: 'transparent',
|
|
75
|
-
padding: 0,
|
|
76
|
-
fontSize: '0.875em',
|
|
77
|
-
},
|
|
78
|
-
'& blockquote': {
|
|
79
|
-
borderLeft: '3px solid',
|
|
80
|
-
borderColor: 'border.default',
|
|
81
|
-
paddingLeft: 3,
|
|
82
|
-
marginLeft: 0,
|
|
83
|
-
color: 'fg.muted',
|
|
84
|
-
},
|
|
85
|
-
'& a': {
|
|
86
|
-
color: 'accent.fg',
|
|
87
|
-
textDecoration: 'underline',
|
|
88
|
-
},
|
|
89
|
-
'& table': {
|
|
90
|
-
width: '100%',
|
|
91
|
-
borderCollapse: 'collapse',
|
|
92
|
-
marginTop: '1em',
|
|
93
|
-
marginBottom: '1em',
|
|
94
|
-
},
|
|
95
|
-
'& th, & td': {
|
|
96
|
-
border: '1px solid',
|
|
97
|
-
borderColor: 'border.default',
|
|
98
|
-
padding: 2,
|
|
99
|
-
textAlign: 'left',
|
|
100
|
-
},
|
|
101
|
-
'& th': {
|
|
102
|
-
backgroundColor: 'canvas.subtle',
|
|
103
|
-
fontWeight: 'bold',
|
|
104
|
-
},
|
|
105
|
-
}, children: _jsx(Streamdown, { children: text }) })] }));
|
|
37
|
+
}, 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: streamdownMarkdownStyles, children: _jsx(Streamdown, { children: text }) })] }));
|
|
106
38
|
}
|
|
107
39
|
export default TextPart;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CSS-in-js styles for Streamdown markdown rendering.
|
|
3
|
+
*
|
|
4
|
+
* Streamdown outputs HTML with Tailwind CSS classes (flex, gap-1, p-1, etc.).
|
|
5
|
+
* Since we don't load Tailwind CSS, we provide equivalent styles via
|
|
6
|
+
* Primer's sx prop targeting the Tailwind class names.
|
|
7
|
+
*
|
|
8
|
+
* @module components/chat/components/styles/streamdownStyles
|
|
9
|
+
*/
|
|
10
|
+
/** Style object compatible with Primer's sx prop */
|
|
11
|
+
type SxStyles = Record<string, unknown>;
|
|
12
|
+
/**
|
|
13
|
+
* Markdown element styles for Streamdown content.
|
|
14
|
+
* Provides proper formatting for headings, lists, tables, code, etc.
|
|
15
|
+
* Uses Primer theme tokens for colors and spacing.
|
|
16
|
+
*/
|
|
17
|
+
export declare const streamdownMarkdownStyles: SxStyles;
|
|
18
|
+
/**
|
|
19
|
+
* Code block specific styles for Streamdown's data-streamdown attributes.
|
|
20
|
+
* These target Streamdown's code block structure.
|
|
21
|
+
*/
|
|
22
|
+
export declare const streamdownCodeBlockStyles: SxStyles;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Tailwind utility class equivalents for Streamdown output.
|
|
7
|
+
* Maps Tailwind class names to CSS properties.
|
|
8
|
+
*/
|
|
9
|
+
const tailwindUtilities = {
|
|
10
|
+
// ── Display / Flexbox ──
|
|
11
|
+
'& .flex': { display: 'flex' },
|
|
12
|
+
'& .inline-block': { display: 'inline-block' },
|
|
13
|
+
'& .block': { display: 'block' },
|
|
14
|
+
'& .hidden': { display: 'none' },
|
|
15
|
+
'& .flex-col': { flexDirection: 'column' },
|
|
16
|
+
'& .items-center': { alignItems: 'center' },
|
|
17
|
+
'& .items-start': { alignItems: 'flex-start' },
|
|
18
|
+
'& .justify-center': { justifyContent: 'center' },
|
|
19
|
+
'& .justify-end': { justifyContent: 'flex-end' },
|
|
20
|
+
'& .justify-between': { justifyContent: 'space-between' },
|
|
21
|
+
'& .flex-shrink-0': { flexShrink: 0 },
|
|
22
|
+
// ── Gap / Spacing ──
|
|
23
|
+
'& .gap-1': { gap: '0.25rem' },
|
|
24
|
+
'& .gap-2': { gap: '0.5rem' },
|
|
25
|
+
'& .space-x-2 > * + *': { marginLeft: '0.5rem' },
|
|
26
|
+
'& .space-y-2 > * + *': { marginTop: '0.5rem' },
|
|
27
|
+
'& .space-y-4 > * + *': { marginTop: '1rem' },
|
|
28
|
+
// ── Padding ──
|
|
29
|
+
'& .p-1': { padding: '0.25rem' },
|
|
30
|
+
'& .p-2': { padding: '0.5rem' },
|
|
31
|
+
'& .p-4': { padding: '1rem' },
|
|
32
|
+
'& .px-1': { paddingLeft: '0.25rem', paddingRight: '0.25rem' },
|
|
33
|
+
'& .px-1\\.5': { paddingLeft: '0.375rem', paddingRight: '0.375rem' },
|
|
34
|
+
'& .px-4': { paddingLeft: '1rem', paddingRight: '1rem' },
|
|
35
|
+
'& .py-0\\.5': { paddingTop: '0.125rem', paddingBottom: '0.125rem' },
|
|
36
|
+
'& .py-1': { paddingTop: '0.25rem', paddingBottom: '0.25rem' },
|
|
37
|
+
'& .py-2': { paddingTop: '0.5rem', paddingBottom: '0.5rem' },
|
|
38
|
+
'& .pl-4': { paddingLeft: '1rem' },
|
|
39
|
+
'& .\\!p-0': { padding: '0 !important' },
|
|
40
|
+
'& .p-1\\.5': { padding: '0.375rem' },
|
|
41
|
+
// ── Margin ──
|
|
42
|
+
'& .mt-1': { marginTop: '0.25rem' },
|
|
43
|
+
'& .mt-2': { marginTop: '0.5rem' },
|
|
44
|
+
'& .mt-6': { marginTop: '1.5rem' },
|
|
45
|
+
'& .mb-2': { marginBottom: '0.5rem' },
|
|
46
|
+
'& .my-4': { marginTop: '1rem', marginBottom: '1rem' },
|
|
47
|
+
'& .my-6': { marginTop: '1.5rem', marginBottom: '1.5rem' },
|
|
48
|
+
'& .mr-2': { marginRight: '0.5rem' },
|
|
49
|
+
// ── Sizing ──
|
|
50
|
+
'& .w-full': { width: '100%' },
|
|
51
|
+
'& .h-full': { height: '100%' },
|
|
52
|
+
'& .h-4': { height: '1rem' },
|
|
53
|
+
'& .w-4': { width: '1rem' },
|
|
54
|
+
'& .h-8': { height: '2rem' },
|
|
55
|
+
'& .w-8': { width: '2rem' },
|
|
56
|
+
'& .size-4': { width: '1rem', height: '1rem' },
|
|
57
|
+
'& .max-w-full': { maxWidth: '100%' },
|
|
58
|
+
'& .min-w-\\[120px\\]': { minWidth: '120px' },
|
|
59
|
+
// ── Typography ──
|
|
60
|
+
'& .text-sm': { fontSize: '0.875rem', lineHeight: '1.25rem' },
|
|
61
|
+
'& .text-xs': { fontSize: '0.75rem', lineHeight: '1rem' },
|
|
62
|
+
'& .text-base': { fontSize: '1rem', lineHeight: '1.5rem' },
|
|
63
|
+
'& .text-lg': { fontSize: '1.125rem', lineHeight: '1.75rem' },
|
|
64
|
+
'& .text-xl': { fontSize: '1.25rem', lineHeight: '1.75rem' },
|
|
65
|
+
'& .text-2xl': { fontSize: '1.5rem', lineHeight: '2rem' },
|
|
66
|
+
'& .text-3xl': { fontSize: '1.875rem', lineHeight: '2.25rem' },
|
|
67
|
+
'& .font-semibold': { fontWeight: 600 },
|
|
68
|
+
'& .font-mono': {
|
|
69
|
+
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
|
|
70
|
+
},
|
|
71
|
+
'& .italic': { fontStyle: 'italic' },
|
|
72
|
+
'& .whitespace-normal': { whiteSpace: 'normal' },
|
|
73
|
+
'& .whitespace-pre-wrap': { whiteSpace: 'pre-wrap' },
|
|
74
|
+
// ── Colors (mapped to Primer theme tokens) ──
|
|
75
|
+
'& .text-muted-foreground': { color: 'fg.muted' },
|
|
76
|
+
'& .text-foreground': { color: 'fg.default' },
|
|
77
|
+
'& .text-red-600': { color: '#dc2626' },
|
|
78
|
+
'& .text-red-700': { color: '#b91c1c' },
|
|
79
|
+
'& .text-red-800': { color: '#991b1b' },
|
|
80
|
+
'& .bg-muted': { backgroundColor: 'neutral.muted' },
|
|
81
|
+
'& .bg-red-50': { backgroundColor: '#fef2f2' },
|
|
82
|
+
'& .bg-red-100': { backgroundColor: '#fee2e2' },
|
|
83
|
+
'& .bg-background': { backgroundColor: 'canvas.default' },
|
|
84
|
+
// ── Background opacity variants ──
|
|
85
|
+
'& .bg-muted\\/80': { backgroundColor: 'neutral.muted' },
|
|
86
|
+
'& .bg-muted\\/40': { backgroundColor: 'neutral.muted' },
|
|
87
|
+
'& .bg-background\\/90': { backgroundColor: 'canvas.default' },
|
|
88
|
+
'& .bg-background\\/95': { backgroundColor: 'canvas.default' },
|
|
89
|
+
'& .bg-black\\/10': { backgroundColor: 'rgba(0,0,0,0.1)' },
|
|
90
|
+
// ── Borders ──
|
|
91
|
+
'& .border': { border: '1px solid', borderColor: 'border.default' },
|
|
92
|
+
'& .border-border': { borderColor: 'border.default' },
|
|
93
|
+
'& .border-b': {
|
|
94
|
+
borderBottom: '1px solid',
|
|
95
|
+
borderBottomColor: 'border.default',
|
|
96
|
+
},
|
|
97
|
+
'& .border-t': { borderTop: '1px solid', borderTopColor: 'border.default' },
|
|
98
|
+
'& .border-l-4': {
|
|
99
|
+
borderLeft: '4px solid',
|
|
100
|
+
borderLeftColor: 'border.default',
|
|
101
|
+
},
|
|
102
|
+
'& .border-red-200': { borderColor: '#fecaca' },
|
|
103
|
+
'& .divide-y > * + *': {
|
|
104
|
+
borderTop: '1px solid',
|
|
105
|
+
borderTopColor: 'border.default',
|
|
106
|
+
},
|
|
107
|
+
'& .divide-border > * + *': { borderColor: 'border.default' },
|
|
108
|
+
// ── Border radius ──
|
|
109
|
+
'& .rounded': { borderRadius: '0.25rem' },
|
|
110
|
+
'& .rounded-md': { borderRadius: '0.375rem' },
|
|
111
|
+
'& .rounded-lg': { borderRadius: '0.5rem' },
|
|
112
|
+
'& .rounded-xl': { borderRadius: '0.75rem' },
|
|
113
|
+
'& .rounded-full': { borderRadius: '9999px' },
|
|
114
|
+
// ── Overflow ──
|
|
115
|
+
'& .overflow-hidden': { overflow: 'hidden' },
|
|
116
|
+
'& .overflow-x-auto': { overflowX: 'auto' },
|
|
117
|
+
'& .overflow-auto': { overflow: 'auto' },
|
|
118
|
+
// ── List styles ──
|
|
119
|
+
'& .list-disc': { listStyleType: 'disc' },
|
|
120
|
+
'& .list-decimal': { listStyleType: 'decimal' },
|
|
121
|
+
'& .list-inside': { listStylePosition: 'inside' },
|
|
122
|
+
// ── Cursor ──
|
|
123
|
+
'& .cursor-pointer': { cursor: 'pointer' },
|
|
124
|
+
// ── Position ──
|
|
125
|
+
'& .relative': { position: 'relative' },
|
|
126
|
+
'& .absolute': { position: 'absolute' },
|
|
127
|
+
'& .fixed': { position: 'fixed' },
|
|
128
|
+
'& .inset-0': { top: 0, right: 0, bottom: 0, left: 0 },
|
|
129
|
+
'& .top-4': { top: '1rem' },
|
|
130
|
+
'& .right-0': { right: 0 },
|
|
131
|
+
'& .right-2': { right: '0.5rem' },
|
|
132
|
+
'& .right-4': { right: '1rem' },
|
|
133
|
+
'& .bottom-2': { bottom: '0.5rem' },
|
|
134
|
+
'& .z-10': { zIndex: 10 },
|
|
135
|
+
'& .z-50': { zIndex: 50 },
|
|
136
|
+
// ── Shadow ──
|
|
137
|
+
'& .shadow-sm': { boxShadow: '0 1px 2px 0 rgba(0,0,0,0.05)' },
|
|
138
|
+
'& .shadow-lg': {
|
|
139
|
+
boxShadow: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',
|
|
140
|
+
},
|
|
141
|
+
// ── Transitions ──
|
|
142
|
+
'& .transition-all': { transition: 'all 150ms ease' },
|
|
143
|
+
'& .transition-colors': {
|
|
144
|
+
transition: 'color 150ms ease, background-color 150ms ease, border-color 150ms ease',
|
|
145
|
+
},
|
|
146
|
+
'& .transition-transform': { transition: 'transform 150ms ease' },
|
|
147
|
+
'& .duration-150': { transitionDuration: '150ms' },
|
|
148
|
+
'& .duration-200': { transitionDuration: '200ms' },
|
|
149
|
+
'& .ease-out': { transitionTimingFunction: 'ease-out' },
|
|
150
|
+
// ── Opacity ──
|
|
151
|
+
'& .opacity-50': { opacity: 0.5 },
|
|
152
|
+
// ── Animation ──
|
|
153
|
+
'& .animate-spin': {
|
|
154
|
+
animation: 'spin 1s linear infinite',
|
|
155
|
+
},
|
|
156
|
+
// ── Hover states ──
|
|
157
|
+
'& .hover\\:text-foreground:hover': { color: 'fg.default' },
|
|
158
|
+
'& .hover\\:bg-muted:hover': { backgroundColor: 'neutral.muted' },
|
|
159
|
+
'& .hover\\:bg-background:hover': { backgroundColor: 'canvas.default' },
|
|
160
|
+
'& .hover\\:block:hover': { display: 'block' },
|
|
161
|
+
'& .group:hover .group-hover\\:block': { display: 'block' },
|
|
162
|
+
// ── Disabled ──
|
|
163
|
+
'& .disabled\\:cursor-not-allowed:disabled': { cursor: 'not-allowed' },
|
|
164
|
+
'& .disabled\\:opacity-50:disabled': { opacity: 0.5 },
|
|
165
|
+
// ── Backdrop ──
|
|
166
|
+
'& .backdrop-blur-sm': { backdropFilter: 'blur(4px)' },
|
|
167
|
+
// ── Misc ──
|
|
168
|
+
'& .pointer-events-none': { pointerEvents: 'none' },
|
|
169
|
+
'& .origin-center': { transformOrigin: 'center' },
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Markdown element styles for Streamdown content.
|
|
173
|
+
* Provides proper formatting for headings, lists, tables, code, etc.
|
|
174
|
+
* Uses Primer theme tokens for colors and spacing.
|
|
175
|
+
*/
|
|
176
|
+
export const streamdownMarkdownStyles = {
|
|
177
|
+
fontSize: 1,
|
|
178
|
+
lineHeight: 1.5,
|
|
179
|
+
'& > *:first-child': { marginTop: 0 },
|
|
180
|
+
'& > *:last-child': { marginBottom: 0 },
|
|
181
|
+
'& p': { marginTop: 0, marginBottom: '0.75em' },
|
|
182
|
+
'& h1, & h2, & h3, & h4, & h5, & h6': {
|
|
183
|
+
marginTop: '1em',
|
|
184
|
+
marginBottom: '0.5em',
|
|
185
|
+
fontWeight: 'bold',
|
|
186
|
+
},
|
|
187
|
+
'& h1': { fontSize: '1.5em' },
|
|
188
|
+
'& h2': { fontSize: '1.3em' },
|
|
189
|
+
'& h3': { fontSize: '1.15em' },
|
|
190
|
+
'& ul, & ol': {
|
|
191
|
+
marginTop: '0.5em',
|
|
192
|
+
marginBottom: '0.5em',
|
|
193
|
+
paddingInlineStart: '1.25em',
|
|
194
|
+
},
|
|
195
|
+
'& li': {
|
|
196
|
+
paddingInlineStart: '0.25em',
|
|
197
|
+
marginBottom: '0.25em',
|
|
198
|
+
},
|
|
199
|
+
'& code': {
|
|
200
|
+
backgroundColor: 'neutral.muted',
|
|
201
|
+
padding: '2px 4px',
|
|
202
|
+
borderRadius: '4px',
|
|
203
|
+
fontSize: '0.9em',
|
|
204
|
+
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
|
|
205
|
+
},
|
|
206
|
+
'& pre code': {
|
|
207
|
+
backgroundColor: 'transparent',
|
|
208
|
+
padding: 0,
|
|
209
|
+
},
|
|
210
|
+
'& blockquote': {
|
|
211
|
+
borderLeft: '3px solid',
|
|
212
|
+
borderColor: 'border.default',
|
|
213
|
+
paddingLeft: '12px',
|
|
214
|
+
marginLeft: 0,
|
|
215
|
+
marginRight: 0,
|
|
216
|
+
color: 'fg.muted',
|
|
217
|
+
},
|
|
218
|
+
'& a': {
|
|
219
|
+
color: 'accent.fg',
|
|
220
|
+
textDecoration: 'underline',
|
|
221
|
+
},
|
|
222
|
+
'& table': {
|
|
223
|
+
width: '100%',
|
|
224
|
+
borderCollapse: 'collapse',
|
|
225
|
+
marginTop: '0.75em',
|
|
226
|
+
marginBottom: '0.75em',
|
|
227
|
+
fontSize: '0.9em',
|
|
228
|
+
},
|
|
229
|
+
'& th, & td': {
|
|
230
|
+
border: '1px solid',
|
|
231
|
+
borderColor: 'border.default',
|
|
232
|
+
padding: '6px 12px',
|
|
233
|
+
textAlign: 'left',
|
|
234
|
+
},
|
|
235
|
+
'& th': {
|
|
236
|
+
backgroundColor: 'canvas.inset',
|
|
237
|
+
fontWeight: 'bold',
|
|
238
|
+
},
|
|
239
|
+
'& tr:nth-of-type(even)': {
|
|
240
|
+
backgroundColor: 'canvas.inset',
|
|
241
|
+
},
|
|
242
|
+
'& img': {
|
|
243
|
+
maxWidth: '100%',
|
|
244
|
+
borderRadius: '8px',
|
|
245
|
+
},
|
|
246
|
+
'& hr': {
|
|
247
|
+
border: 'none',
|
|
248
|
+
borderTop: '1px solid',
|
|
249
|
+
borderColor: 'border.default',
|
|
250
|
+
marginTop: '1em',
|
|
251
|
+
marginBottom: '1em',
|
|
252
|
+
},
|
|
253
|
+
// Include Tailwind utilities for Streamdown output
|
|
254
|
+
...tailwindUtilities,
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Code block specific styles for Streamdown's data-streamdown attributes.
|
|
258
|
+
* These target Streamdown's code block structure.
|
|
259
|
+
*/
|
|
260
|
+
export const streamdownCodeBlockStyles = {
|
|
261
|
+
'& [data-streamdown="code-block"]': {
|
|
262
|
+
borderRadius: '8px',
|
|
263
|
+
border: '1px solid',
|
|
264
|
+
borderColor: 'border.default',
|
|
265
|
+
overflow: 'hidden',
|
|
266
|
+
my: 2,
|
|
267
|
+
},
|
|
268
|
+
'& [data-streamdown="code-block-header"]': {
|
|
269
|
+
display: 'flex',
|
|
270
|
+
alignItems: 'center',
|
|
271
|
+
justifyContent: 'space-between',
|
|
272
|
+
backgroundColor: 'canvas.subtle',
|
|
273
|
+
padding: '8px 12px',
|
|
274
|
+
fontSize: '12px',
|
|
275
|
+
color: 'fg.muted',
|
|
276
|
+
},
|
|
277
|
+
'& [data-streamdown="code-block-header"] button': {
|
|
278
|
+
background: 'none',
|
|
279
|
+
border: 'none',
|
|
280
|
+
cursor: 'pointer',
|
|
281
|
+
padding: '4px',
|
|
282
|
+
color: 'fg.muted',
|
|
283
|
+
borderRadius: '4px',
|
|
284
|
+
'&:hover': {
|
|
285
|
+
backgroundColor: 'neutral.muted',
|
|
286
|
+
color: 'fg.default',
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
'& [data-streamdown="code-block-body"]': {
|
|
290
|
+
backgroundColor: 'canvas.subtle',
|
|
291
|
+
padding: '12px',
|
|
292
|
+
margin: 0,
|
|
293
|
+
overflow: 'auto',
|
|
294
|
+
fontSize: '13px',
|
|
295
|
+
lineHeight: 1.5,
|
|
296
|
+
},
|
|
297
|
+
'& [data-streamdown="code-block-body"] code': {
|
|
298
|
+
display: 'block',
|
|
299
|
+
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
|
|
300
|
+
},
|
|
301
|
+
'& [data-streamdown="code-block-body"] code > span.block': {
|
|
302
|
+
display: 'block',
|
|
303
|
+
},
|
|
304
|
+
'& [data-streamdown="code-block-body"] code > span': {
|
|
305
|
+
display: 'block',
|
|
306
|
+
},
|
|
307
|
+
'& pre': {
|
|
308
|
+
whiteSpace: 'pre-wrap',
|
|
309
|
+
wordBreak: 'break-word',
|
|
310
|
+
overflowX: 'auto',
|
|
311
|
+
margin: 0,
|
|
312
|
+
},
|
|
313
|
+
'& pre code': {
|
|
314
|
+
whiteSpace: 'pre-wrap',
|
|
315
|
+
},
|
|
316
|
+
'& code': {
|
|
317
|
+
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
|
|
318
|
+
},
|
|
319
|
+
};
|