@datalayer/agent-runtimes 0.0.11 → 0.0.12
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 +34 -0
- package/lib/AgentLexical.js +296 -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/AgentRuntimeLexicalExample.js +6 -3
- package/lib/examples/AgentRuntimeLexicalSidebarExample.js +8 -1
- package/lib/examples/AgentRuntimeNotebookExample.js +6 -5
- 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 +41 -179
- package/lib/lexical/index.d.ts +1 -0
- package/lib/lexical/index.js +1 -0
- package/lib/lexical/useChatInlineToolbarItems.d.ts +28 -0
- package/lib/lexical/useChatInlineToolbarItems.js +163 -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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
@@ -6,27 +6,41 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
/**
|
|
7
7
|
* ChatInlinePlugin - Lexical plugin for inline AI chat.
|
|
8
8
|
*
|
|
9
|
-
* This plugin displays a floating AI chat interface when
|
|
10
|
-
*
|
|
11
|
-
* like improve, summarize, translate, etc.
|
|
9
|
+
* This plugin displays a floating AI chat interface when the user triggers
|
|
10
|
+
* an AI action (via the toolbar's AI dropdown or sparkle button). It provides
|
|
11
|
+
* AI-powered text manipulation features like improve, summarize, translate, etc.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
13
|
+
* IMPORTANT: This plugin no longer renders its own formatting toolbar.
|
|
14
|
+
* Instead, AI actions are registered as `extraItems` in the
|
|
15
|
+
* `FloatingTextFormatToolbarPlugin` via the `useChatInlineToolbarItems` hook.
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const { toolbarItems, isAiOpen, pendingPrompt, clearPendingPrompt, closeAi } =
|
|
20
|
+
* useChatInlineToolbarItems();
|
|
21
|
+
*
|
|
22
|
+
* <FloatingTextFormatToolbarPlugin
|
|
23
|
+
* anchorElem={floatingAnchorElem}
|
|
24
|
+
* setIsLinkEditMode={setIsLinkEditMode}
|
|
25
|
+
* extraItems={toolbarItems}
|
|
26
|
+
* />
|
|
27
|
+
* <ChatInlinePlugin
|
|
28
|
+
* protocol={protocol}
|
|
29
|
+
* isOpen={isAiOpen}
|
|
30
|
+
* onClose={closeAi}
|
|
31
|
+
* pendingPrompt={pendingPrompt}
|
|
32
|
+
* onPendingPromptConsumed={clearPendingPrompt}
|
|
33
|
+
* />
|
|
34
|
+
* ```
|
|
19
35
|
*
|
|
20
36
|
* @module lexical/ChatInlinePlugin
|
|
21
37
|
*/
|
|
22
38
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from 'react';
|
|
23
39
|
import { createPortal } from 'react-dom';
|
|
24
|
-
import { $getSelection, $isRangeSelection, $createParagraphNode, $createTextNode, TextNode, COMMAND_PRIORITY_LOW, createCommand,
|
|
25
|
-
import { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
|
|
40
|
+
import { $getSelection, $isRangeSelection, $createParagraphNode, $createTextNode, TextNode, COMMAND_PRIORITY_LOW, createCommand, } from 'lexical';
|
|
26
41
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
27
42
|
import { autoUpdate, hide, limitShift, offset, shift, size, useFloating, } from '@floating-ui/react-dom';
|
|
28
|
-
import { Box
|
|
29
|
-
import { BoldIcon, ItalicIcon, StrikethroughIcon, CodeIcon, LinkIcon, SparkleFillIcon, } from '@primer/octicons-react';
|
|
43
|
+
import { Box } from '@primer/react';
|
|
30
44
|
import { ChatInline, } from '../components/chat/components/ChatInline';
|
|
31
45
|
// Margin from editor edges
|
|
32
46
|
const MARGIN_X = 32;
|
|
@@ -53,7 +67,6 @@ function usePreserveSelection(editor) {
|
|
|
53
67
|
editor.update(() => {
|
|
54
68
|
const selection = savedSelectionRef.current;
|
|
55
69
|
if (selection) {
|
|
56
|
-
// Note: We create a new reference to avoid stale selection issues
|
|
57
70
|
try {
|
|
58
71
|
const anchor = selection.anchor;
|
|
59
72
|
const focus = selection.focus;
|
|
@@ -83,16 +96,13 @@ function usePreserveSelection(editor) {
|
|
|
83
96
|
}
|
|
84
97
|
/**
|
|
85
98
|
* Hook to get current text selection range
|
|
86
|
-
* Uses native DOM selection for immediate response during drag operations
|
|
87
99
|
*/
|
|
88
100
|
function useRange() {
|
|
89
101
|
const [editor] = useLexicalComposerContext();
|
|
90
102
|
const [range, setRange] = useState(null);
|
|
91
103
|
useEffect(() => {
|
|
92
|
-
// Function to update range from DOM selection
|
|
93
104
|
const updateRange = () => {
|
|
94
105
|
const domSelection = window.getSelection();
|
|
95
|
-
// Check if selection exists and is within the editor
|
|
96
106
|
if (!domSelection ||
|
|
97
107
|
domSelection.rangeCount === 0 ||
|
|
98
108
|
!editor._rootElement) {
|
|
@@ -100,26 +110,21 @@ function useRange() {
|
|
|
100
110
|
return;
|
|
101
111
|
}
|
|
102
112
|
const domRange = domSelection.getRangeAt(0);
|
|
103
|
-
// Check if selection is within the editor
|
|
104
113
|
if (!editor._rootElement.contains(domRange.commonAncestorContainer)) {
|
|
105
114
|
setRange(null);
|
|
106
115
|
return;
|
|
107
116
|
}
|
|
108
|
-
// Check if selection is collapsed (just a cursor, no text selected)
|
|
109
117
|
if (domRange.collapsed) {
|
|
110
118
|
setRange(null);
|
|
111
119
|
return;
|
|
112
120
|
}
|
|
113
121
|
setRange(domRange.cloneRange());
|
|
114
122
|
};
|
|
115
|
-
// Listen for Lexical editor updates
|
|
116
123
|
const unregister = editor.registerUpdateListener(({ tags }) => {
|
|
117
|
-
// Ignore collaboration updates
|
|
118
124
|
if (tags.has('collaboration'))
|
|
119
125
|
return;
|
|
120
126
|
updateRange();
|
|
121
127
|
});
|
|
122
|
-
// Listen for DOM selection changes to catch drag selections
|
|
123
128
|
document.addEventListener('selectionchange', updateRange);
|
|
124
129
|
return () => {
|
|
125
130
|
unregister();
|
|
@@ -145,91 +150,18 @@ function useSelectionText() {
|
|
|
145
150
|
return textContent;
|
|
146
151
|
}
|
|
147
152
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const [isMouseDownOutside, setIsMouseDownOutside] = useState(false);
|
|
153
|
-
// Force update counter to trigger re-render on mouseup
|
|
154
|
-
const [, forceUpdate] = useState(0);
|
|
155
|
-
useEffect(() => {
|
|
156
|
-
const handleMouseDown = (e) => {
|
|
157
|
-
const element = getElement();
|
|
158
|
-
// Check if the click is outside the toolbar element
|
|
159
|
-
if (element && element.contains(e.target)) {
|
|
160
|
-
// Click is inside toolbar, don't set mouse down state
|
|
161
|
-
setIsMouseDownOutside(false);
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
// Click is outside toolbar (in editor), set mouse down state
|
|
165
|
-
setIsMouseDownOutside(true);
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
const handleMouseUp = () => {
|
|
169
|
-
setIsMouseDownOutside(false);
|
|
170
|
-
// Force a re-render to show toolbar after selection completes
|
|
171
|
-
forceUpdate(n => n + 1);
|
|
172
|
-
};
|
|
173
|
-
document.addEventListener('mousedown', handleMouseDown);
|
|
174
|
-
document.addEventListener('mouseup', handleMouseUp);
|
|
175
|
-
return () => {
|
|
176
|
-
document.removeEventListener('mousedown', handleMouseDown);
|
|
177
|
-
document.removeEventListener('mouseup', handleMouseUp);
|
|
178
|
-
};
|
|
179
|
-
}, [getElement]);
|
|
180
|
-
return isMouseDownOutside;
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* ChatInlinePlugin - Floating AI toolbar for Lexical text selection.
|
|
153
|
+
* ChatInlinePlugin - Floating AI chat panel for Lexical text selection.
|
|
154
|
+
*
|
|
155
|
+
* This plugin is controlled externally via `isOpen` prop. It positions a
|
|
156
|
+
* ChatInline component near the text selection when open.
|
|
184
157
|
*/
|
|
185
|
-
export function ChatInlinePlugin({ protocol, portalContainer, }) {
|
|
158
|
+
export function ChatInlinePlugin({ protocol, isOpen, onClose, pendingPrompt, onPendingPromptConsumed, portalContainer, }) {
|
|
186
159
|
const [editor] = useLexicalComposerContext();
|
|
187
|
-
const [toolbarState, setToolbarState] = useState('closed');
|
|
188
|
-
const [fullWidth, setFullWidth] = useState(false);
|
|
189
160
|
const padding = 20;
|
|
190
|
-
// Text format state
|
|
191
|
-
const [isBold, setIsBold] = useState(false);
|
|
192
|
-
const [isItalic, setIsItalic] = useState(false);
|
|
193
|
-
const [isStrikethrough, setIsStrikethrough] = useState(false);
|
|
194
|
-
const [isCode, setIsCode] = useState(false);
|
|
195
|
-
const [isLink, setIsLink] = useState(false);
|
|
196
|
-
// Update text format state based on selection
|
|
197
|
-
const updateFormatState = useCallback(() => {
|
|
198
|
-
editor.getEditorState().read(() => {
|
|
199
|
-
const selection = $getSelection();
|
|
200
|
-
if ($isRangeSelection(selection)) {
|
|
201
|
-
setIsBold(selection.hasFormat('bold'));
|
|
202
|
-
setIsItalic(selection.hasFormat('italic'));
|
|
203
|
-
setIsStrikethrough(selection.hasFormat('strikethrough'));
|
|
204
|
-
setIsCode(selection.hasFormat('code'));
|
|
205
|
-
// Check if selection contains a link
|
|
206
|
-
const nodes = selection.getNodes();
|
|
207
|
-
const isLinkNode = nodes.some(node => {
|
|
208
|
-
const parent = node.getParent();
|
|
209
|
-
return $isLinkNode(parent) || $isLinkNode(node);
|
|
210
|
-
});
|
|
211
|
-
setIsLink(isLinkNode);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
}, [editor]);
|
|
215
|
-
// Listen for selection changes to update format state
|
|
216
|
-
useEffect(() => {
|
|
217
|
-
return editor.registerUpdateListener(({ editorState }) => {
|
|
218
|
-
editorState.read(() => {
|
|
219
|
-
updateFormatState();
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
}, [editor, updateFormatState]);
|
|
223
161
|
// Selection preservation
|
|
224
162
|
const { saveSelection, restoreSelection } = usePreserveSelection(editor);
|
|
225
|
-
// Ref for the toolbar container to detect clicks inside vs outside
|
|
226
|
-
const toolbarRef = useRef(null);
|
|
227
|
-
// Stable getter function for the toolbar element
|
|
228
|
-
const getToolbarElement = useCallback(() => toolbarRef.current, []);
|
|
229
|
-
// Track mouse state for detecting ongoing drag selections (only outside toolbar)
|
|
230
|
-
const isMouseDownOutside = useIsMouseDownOutside(getToolbarElement);
|
|
231
163
|
// Floating UI setup
|
|
232
|
-
const { refs: { setReference, setFloating }, strategy,
|
|
164
|
+
const { refs: { setReference, setFloating }, strategy, y, } = useFloating({
|
|
233
165
|
strategy: 'fixed',
|
|
234
166
|
placement: 'bottom',
|
|
235
167
|
middleware: [
|
|
@@ -253,17 +185,6 @@ export function ChatInlinePlugin({ protocol, portalContainer, }) {
|
|
|
253
185
|
getBoundingClientRect: () => range?.getBoundingClientRect() || new DOMRect(),
|
|
254
186
|
});
|
|
255
187
|
}, [setReference, range]);
|
|
256
|
-
// Reset width when selection is removed, show button when selection appears
|
|
257
|
-
useEffect(() => {
|
|
258
|
-
if (range === null) {
|
|
259
|
-
setFullWidth(false);
|
|
260
|
-
setToolbarState('closed');
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
// Only transition from closed to button, not from ai to button
|
|
264
|
-
setToolbarState(prev => (prev === 'closed' ? 'button' : prev));
|
|
265
|
-
}
|
|
266
|
-
}, [range]);
|
|
267
188
|
// Handle replace selection
|
|
268
189
|
const handleReplaceSelection = useCallback((text) => {
|
|
269
190
|
editor.update(() => {
|
|
@@ -298,82 +219,23 @@ export function ChatInlinePlugin({ protocol, portalContainer, }) {
|
|
|
298
219
|
}
|
|
299
220
|
});
|
|
300
221
|
}, [editor]);
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
setToolbarState('button');
|
|
304
|
-
setFullWidth(false);
|
|
305
|
-
}, []);
|
|
306
|
-
// Handle open AI
|
|
307
|
-
const handleOpenAI = useCallback(() => {
|
|
308
|
-
setToolbarState('ai');
|
|
309
|
-
setFullWidth(true);
|
|
310
|
-
}, []);
|
|
311
|
-
// Text formatting handlers
|
|
312
|
-
const handleFormat = useCallback((format) => {
|
|
313
|
-
editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
|
|
314
|
-
}, [editor]);
|
|
315
|
-
const handleToggleLink = useCallback(() => {
|
|
316
|
-
if (isLink) {
|
|
317
|
-
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
editor.dispatchCommand(TOGGLE_LINK_COMMAND, 'https://');
|
|
321
|
-
}
|
|
322
|
-
}, [editor, isLink]);
|
|
323
|
-
// Don't render if no selection, mouse is still down outside toolbar (dragging), or toolbar closed
|
|
324
|
-
if (range === null || isMouseDownOutside || toolbarState === 'closed') {
|
|
222
|
+
// Don't render if not open or no selection
|
|
223
|
+
if (!isOpen || range === null) {
|
|
325
224
|
return null;
|
|
326
225
|
}
|
|
327
226
|
const portalTarget = portalContainer || document.body;
|
|
328
|
-
return createPortal(
|
|
329
|
-
setFloating(el);
|
|
330
|
-
toolbarRef.current =
|
|
331
|
-
el;
|
|
332
|
-
}, sx: {
|
|
227
|
+
return createPortal(_jsx(Box, { ref: setFloating, sx: {
|
|
333
228
|
pointerEvents: 'auto',
|
|
334
229
|
zIndex: 50,
|
|
335
230
|
position: strategy,
|
|
336
231
|
top: 0,
|
|
337
|
-
left:
|
|
232
|
+
left: editor._rootElement
|
|
338
233
|
? editor._rootElement.getBoundingClientRect().left + MARGIN_X
|
|
339
234
|
: 0,
|
|
340
|
-
transform:
|
|
341
|
-
|
|
342
|
-
: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,
|
|
343
|
-
width: fullWidth && editor._rootElement
|
|
235
|
+
transform: `translate3d(0, ${Math.round(y)}px, 0)`,
|
|
236
|
+
width: editor._rootElement
|
|
344
237
|
? editor._rootElement.getBoundingClientRect().width - MARGIN_X * 2
|
|
345
238
|
: 'auto',
|
|
346
|
-
|
|
347
|
-
}, children: [toolbarState === 'button' && (_jsxs(Box, { sx: {
|
|
348
|
-
display: 'flex',
|
|
349
|
-
alignItems: 'center',
|
|
350
|
-
gap: 0,
|
|
351
|
-
p: 1,
|
|
352
|
-
borderRadius: '12px',
|
|
353
|
-
border: '1px solid',
|
|
354
|
-
borderColor: 'border.default',
|
|
355
|
-
boxShadow: 'shadow.large',
|
|
356
|
-
bg: 'canvas.default',
|
|
357
|
-
}, children: [_jsx(IconButton, { icon: BoldIcon, "aria-label": "Bold", variant: "invisible", onClick: () => handleFormat('bold'), sx: {
|
|
358
|
-
color: isBold ? 'accent.fg' : 'fg.muted',
|
|
359
|
-
bg: isBold ? 'accent.subtle' : 'transparent',
|
|
360
|
-
} }), _jsx(IconButton, { icon: ItalicIcon, "aria-label": "Italic", variant: "invisible", onClick: () => handleFormat('italic'), sx: {
|
|
361
|
-
color: isItalic ? 'accent.fg' : 'fg.muted',
|
|
362
|
-
bg: isItalic ? 'accent.subtle' : 'transparent',
|
|
363
|
-
} }), _jsx(IconButton, { icon: StrikethroughIcon, "aria-label": "Strikethrough", variant: "invisible", onClick: () => handleFormat('strikethrough'), sx: {
|
|
364
|
-
color: isStrikethrough ? 'accent.fg' : 'fg.muted',
|
|
365
|
-
bg: isStrikethrough ? 'accent.subtle' : 'transparent',
|
|
366
|
-
} }), _jsx(IconButton, { icon: CodeIcon, "aria-label": "Code", variant: "invisible", onClick: () => handleFormat('code'), sx: {
|
|
367
|
-
color: isCode ? 'accent.fg' : 'fg.muted',
|
|
368
|
-
bg: isCode ? 'accent.subtle' : 'transparent',
|
|
369
|
-
} }), _jsx(IconButton, { icon: LinkIcon, "aria-label": "Link", variant: "invisible", onClick: handleToggleLink, sx: {
|
|
370
|
-
color: isLink ? 'accent.fg' : 'fg.muted',
|
|
371
|
-
bg: isLink ? 'accent.subtle' : 'transparent',
|
|
372
|
-
} }), _jsx(Box, { sx: {
|
|
373
|
-
width: '1px',
|
|
374
|
-
height: '16px',
|
|
375
|
-
bg: 'border.default',
|
|
376
|
-
mx: 1,
|
|
377
|
-
} }), _jsx(IconButton, { icon: SparkleFillIcon, "aria-label": "AI Assistant", variant: "invisible", onClick: handleOpenAI, sx: { color: 'fg.muted' } })] })), toolbarState === 'ai' && (_jsx(ChatInline, { selectedText: selectedText, protocol: protocol, onReplaceSelection: handleReplaceSelection, onInsertInline: handleInsertInline, onInsertBelow: handleInsertBelow, onClose: handleClose, onSaveSelection: saveSelection, onRestoreSelection: restoreSelection }))] }), portalTarget);
|
|
239
|
+
}, children: _jsx(ChatInline, { selectedText: selectedText, protocol: protocol, onReplaceSelection: handleReplaceSelection, onInsertInline: handleInsertInline, onInsertBelow: handleInsertBelow, onClose: onClose, onSaveSelection: saveSelection, onRestoreSelection: restoreSelection, pendingPrompt: pendingPrompt, onPendingPromptConsumed: onPendingPromptConsumed }) }), portalTarget);
|
|
378
240
|
}
|
|
379
241
|
export default ChatInlinePlugin;
|
package/lib/lexical/index.d.ts
CHANGED
package/lib/lexical/index.js
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ToolbarItem } from '@datalayer/primer-addons';
|
|
2
|
+
/**
|
|
3
|
+
* Return type for useChatInlineToolbarItems.
|
|
4
|
+
*/
|
|
5
|
+
export interface ChatInlineToolbarState {
|
|
6
|
+
/** ToolbarItem[] to pass as extraItems to FloatingTextFormatToolbarPlugin */
|
|
7
|
+
toolbarItems: ToolbarItem[];
|
|
8
|
+
/** Whether the AI inline chat panel is open */
|
|
9
|
+
isAiOpen: boolean;
|
|
10
|
+
/** Submit a prompt directly (used by the dropdown actions) */
|
|
11
|
+
submitPrompt: (prompt: string) => void;
|
|
12
|
+
/** The pending prompt (set by dropdown, consumed by ChatInlinePlugin) */
|
|
13
|
+
pendingPrompt: string | null;
|
|
14
|
+
/** Clear the pending prompt after it has been consumed */
|
|
15
|
+
clearPendingPrompt: () => void;
|
|
16
|
+
/** Open the AI panel (with custom prompt input) */
|
|
17
|
+
openAi: () => void;
|
|
18
|
+
/** Close the AI panel */
|
|
19
|
+
closeAi: () => void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Hook that creates ToolbarItem[] for AI actions in the floating toolbar.
|
|
23
|
+
*
|
|
24
|
+
* Returns toolbar items (divider + AI dropdown + sparkle button) and
|
|
25
|
+
* state for controlling the ChatInline panel.
|
|
26
|
+
*/
|
|
27
|
+
export declare function useChatInlineToolbarItems(): ChatInlineToolbarState;
|
|
28
|
+
export default useChatInlineToolbarItems;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* useChatInlineToolbarItems - Hook that creates ToolbarItem[] for the
|
|
7
|
+
* FloatingTextFormatToolbarPlugin's extraItems prop.
|
|
8
|
+
*
|
|
9
|
+
* Registers an AI sparkle button + dropdown with AI actions
|
|
10
|
+
* (Improve, Fix, Simplify, Add detail, Summarise, Explain, Translate)
|
|
11
|
+
* into the floating inline toolbar.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const { toolbarItems, isAiOpen, submitPrompt, closeAi } = useChatInlineToolbarItems();
|
|
16
|
+
*
|
|
17
|
+
* <FloatingTextFormatToolbarPlugin
|
|
18
|
+
* anchorElem={floatingAnchorElem}
|
|
19
|
+
* setIsLinkEditMode={setIsLinkEditMode}
|
|
20
|
+
* extraItems={toolbarItems}
|
|
21
|
+
* />
|
|
22
|
+
*
|
|
23
|
+
* {isAiOpen && <ChatInlinePlugin ... />}
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @module lexical/useChatInlineToolbarItems
|
|
27
|
+
*/
|
|
28
|
+
import { useState, useMemo, useCallback } from 'react';
|
|
29
|
+
import { SparkleFillIcon, PencilIcon, CheckIcon, XIcon, PlusIcon, CopyIcon, SyncIcon, InfoIcon, } from '@primer/octicons-react';
|
|
30
|
+
/**
|
|
31
|
+
* AI action groups for the toolbar dropdown.
|
|
32
|
+
*/
|
|
33
|
+
const AI_ACTIONS = {
|
|
34
|
+
modify: [
|
|
35
|
+
{
|
|
36
|
+
key: 'ai-improve',
|
|
37
|
+
label: 'Improve writing',
|
|
38
|
+
prompt: 'Improve the quality of the text',
|
|
39
|
+
icon: PencilIcon,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
key: 'ai-fix',
|
|
43
|
+
label: 'Fix mistakes',
|
|
44
|
+
prompt: 'Fix any typos or general errors in the text',
|
|
45
|
+
icon: CheckIcon,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
key: 'ai-simplify',
|
|
49
|
+
label: 'Simplify',
|
|
50
|
+
prompt: 'Shorten the text, simplifying it',
|
|
51
|
+
icon: XIcon,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
key: 'ai-detail',
|
|
55
|
+
label: 'Add more detail',
|
|
56
|
+
prompt: 'Lengthen the text, going into more detail',
|
|
57
|
+
icon: PlusIcon,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
generate: [
|
|
61
|
+
{
|
|
62
|
+
key: 'ai-summarise',
|
|
63
|
+
label: 'Summarise',
|
|
64
|
+
prompt: 'Summarise the text',
|
|
65
|
+
icon: CopyIcon,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
key: 'ai-explain',
|
|
69
|
+
label: 'Explain',
|
|
70
|
+
prompt: 'Explain what the text is about',
|
|
71
|
+
icon: InfoIcon,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
translate: [
|
|
75
|
+
'Arabic',
|
|
76
|
+
'Chinese',
|
|
77
|
+
'Dutch',
|
|
78
|
+
'English',
|
|
79
|
+
'French',
|
|
80
|
+
'German',
|
|
81
|
+
'Japanese',
|
|
82
|
+
'Korean',
|
|
83
|
+
'Portuguese',
|
|
84
|
+
'Spanish',
|
|
85
|
+
].map(lang => ({
|
|
86
|
+
key: `ai-translate-${lang.toLowerCase()}`,
|
|
87
|
+
label: lang,
|
|
88
|
+
prompt: `Translate text into the ${lang} language`,
|
|
89
|
+
icon: SyncIcon,
|
|
90
|
+
})),
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Hook that creates ToolbarItem[] for AI actions in the floating toolbar.
|
|
94
|
+
*
|
|
95
|
+
* Returns toolbar items (divider + AI dropdown + sparkle button) and
|
|
96
|
+
* state for controlling the ChatInline panel.
|
|
97
|
+
*/
|
|
98
|
+
export function useChatInlineToolbarItems() {
|
|
99
|
+
const [isAiOpen, setIsAiOpen] = useState(false);
|
|
100
|
+
const [pendingPrompt, setPendingPrompt] = useState(null);
|
|
101
|
+
const openAi = useCallback(() => {
|
|
102
|
+
setIsAiOpen(true);
|
|
103
|
+
}, []);
|
|
104
|
+
const closeAi = useCallback(() => {
|
|
105
|
+
setIsAiOpen(false);
|
|
106
|
+
setPendingPrompt(null);
|
|
107
|
+
}, []);
|
|
108
|
+
const submitPrompt = useCallback((prompt) => {
|
|
109
|
+
setPendingPrompt(prompt);
|
|
110
|
+
setIsAiOpen(true);
|
|
111
|
+
}, []);
|
|
112
|
+
const clearPendingPrompt = useCallback(() => {
|
|
113
|
+
setPendingPrompt(null);
|
|
114
|
+
}, []);
|
|
115
|
+
const toolbarItems = useMemo(() => {
|
|
116
|
+
const allOptions = [
|
|
117
|
+
...AI_ACTIONS.modify.map(action => ({
|
|
118
|
+
key: action.key,
|
|
119
|
+
label: action.label,
|
|
120
|
+
icon: action.icon,
|
|
121
|
+
onClick: () => submitPrompt(action.prompt),
|
|
122
|
+
})),
|
|
123
|
+
...AI_ACTIONS.generate.map(action => ({
|
|
124
|
+
key: action.key,
|
|
125
|
+
label: action.label,
|
|
126
|
+
icon: action.icon,
|
|
127
|
+
onClick: () => submitPrompt(action.prompt),
|
|
128
|
+
})),
|
|
129
|
+
...AI_ACTIONS.translate.map(action => ({
|
|
130
|
+
key: action.key,
|
|
131
|
+
label: action.label,
|
|
132
|
+
icon: action.icon,
|
|
133
|
+
onClick: () => submitPrompt(action.prompt),
|
|
134
|
+
})),
|
|
135
|
+
];
|
|
136
|
+
return [
|
|
137
|
+
{
|
|
138
|
+
key: 'ai-divider',
|
|
139
|
+
type: 'divider',
|
|
140
|
+
order: 900,
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
key: 'ai-actions',
|
|
144
|
+
type: 'dropdown',
|
|
145
|
+
order: 901,
|
|
146
|
+
ariaLabel: 'AI Actions',
|
|
147
|
+
title: 'AI Actions',
|
|
148
|
+
icon: SparkleFillIcon,
|
|
149
|
+
options: allOptions,
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
}, [submitPrompt]);
|
|
153
|
+
return {
|
|
154
|
+
toolbarItems,
|
|
155
|
+
isAiOpen,
|
|
156
|
+
submitPrompt,
|
|
157
|
+
pendingPrompt,
|
|
158
|
+
clearPendingPrompt,
|
|
159
|
+
openAi,
|
|
160
|
+
closeAi,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
export default useChatInlineToolbarItems;
|
|
@@ -82,7 +82,7 @@ export interface UseAgentRuntimeReturn {
|
|
|
82
82
|
* <>
|
|
83
83
|
* <Notebook />
|
|
84
84
|
* {isReady && (
|
|
85
|
-
* <ChatFloating endpoint={endpoint}
|
|
85
|
+
* <ChatFloating endpoint={endpoint} frontendTools={frontendTools} />
|
|
86
86
|
* )}
|
|
87
87
|
* {error && <ErrorBanner>{error}</ErrorBanner>}
|
|
88
88
|
* </>
|
|
@@ -57,7 +57,7 @@ import { useRuntimeStore, useRuntime, useAgent, useRuntimeStatus, useRuntimeErro
|
|
|
57
57
|
* <>
|
|
58
58
|
* <Notebook />
|
|
59
59
|
* {isReady && (
|
|
60
|
-
* <ChatFloating endpoint={endpoint}
|
|
60
|
+
* <ChatFloating endpoint={endpoint} frontendTools={frontendTools} />
|
|
61
61
|
* )}
|
|
62
62
|
* {error && <ErrorBanner>{error}</ErrorBanner>}
|
|
63
63
|
* </>
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* THIS FILE IS AUTO-GENERATED. DO NOT EDIT MANUALLY.
|
|
6
6
|
* Generated from YAML specifications in specs/agents/
|
|
7
7
|
*/
|
|
8
|
-
import type { AgentSpec } from '../../../types';
|
|
8
|
+
import type { AgentSpec } from '../../../types/Types';
|
|
9
|
+
export declare const DATA_ACQUISITION_AGENT_SPEC: AgentSpec;
|
|
9
10
|
export declare const SIMPLE_AGENT_SPEC: AgentSpec;
|
|
10
11
|
export declare const AGENT_SPECS: Record<string, AgentSpec>;
|
|
11
12
|
/**
|
|
@@ -14,8 +15,10 @@ export declare const AGENT_SPECS: Record<string, AgentSpec>;
|
|
|
14
15
|
export declare function getAgentSpecs(agentId: string): AgentSpec | undefined;
|
|
15
16
|
/**
|
|
16
17
|
* List all available agent specifications.
|
|
18
|
+
*
|
|
19
|
+
* @param prefix - If provided, only return specs whose ID starts with this prefix.
|
|
17
20
|
*/
|
|
18
|
-
export declare function listAgentSpecs(): AgentSpec[];
|
|
21
|
+
export declare function listAgentSpecs(prefix?: string): AgentSpec[];
|
|
19
22
|
/**
|
|
20
23
|
* Collect all required environment variables for an agent spec.
|
|
21
24
|
*
|