@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
|
@@ -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
|
-
import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from 'react';
|
|
38
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, 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: [
|
|
@@ -247,23 +179,33 @@ export function ChatInlinePlugin({ protocol, portalContainer, }) {
|
|
|
247
179
|
// Selection tracking
|
|
248
180
|
const { range } = useRange();
|
|
249
181
|
const selectedText = useSelectionText();
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
182
|
+
// ---------------------------------------------------------------
|
|
183
|
+
// Latch: save position & text when AI panel opens so that a
|
|
184
|
+
// transient selection loss (e.g. portal render triggering
|
|
185
|
+
// selectionchange) does not unmount the panel.
|
|
186
|
+
// ---------------------------------------------------------------
|
|
187
|
+
const savedRectRef = useRef(null);
|
|
188
|
+
const savedTextRef = useRef('');
|
|
257
189
|
useEffect(() => {
|
|
258
|
-
if (
|
|
259
|
-
|
|
260
|
-
|
|
190
|
+
if (isOpen && range) {
|
|
191
|
+
// Keep saving the latest rect/text while open and range is valid
|
|
192
|
+
savedRectRef.current = range.getBoundingClientRect();
|
|
193
|
+
savedTextRef.current = selectedText || '';
|
|
261
194
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
195
|
+
if (!isOpen) {
|
|
196
|
+
savedRectRef.current = null;
|
|
197
|
+
savedTextRef.current = '';
|
|
265
198
|
}
|
|
266
|
-
}, [range]);
|
|
199
|
+
}, [isOpen, range, selectedText]);
|
|
200
|
+
// Effective values: prefer live selection, fall back to saved snapshot
|
|
201
|
+
const effectiveRect = useMemo(() => range?.getBoundingClientRect() ?? savedRectRef.current ?? null, [range]);
|
|
202
|
+
const effectiveText = range ? selectedText : savedTextRef.current;
|
|
203
|
+
// Update floating reference position based on selection (or saved rect)
|
|
204
|
+
useLayoutEffect(() => {
|
|
205
|
+
setReference({
|
|
206
|
+
getBoundingClientRect: () => effectiveRect || new DOMRect(),
|
|
207
|
+
});
|
|
208
|
+
}, [setReference, effectiveRect]);
|
|
267
209
|
// Handle replace selection
|
|
268
210
|
const handleReplaceSelection = useCallback((text) => {
|
|
269
211
|
editor.update(() => {
|
|
@@ -298,82 +240,23 @@ export function ChatInlinePlugin({ protocol, portalContainer, }) {
|
|
|
298
240
|
}
|
|
299
241
|
});
|
|
300
242
|
}, [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') {
|
|
243
|
+
// Don't render if not open, or if we have neither a live range nor a saved rect
|
|
244
|
+
if (!isOpen || (range === null && savedRectRef.current === null)) {
|
|
325
245
|
return null;
|
|
326
246
|
}
|
|
327
247
|
const portalTarget = portalContainer || document.body;
|
|
328
|
-
return createPortal(
|
|
329
|
-
setFloating(el);
|
|
330
|
-
toolbarRef.current =
|
|
331
|
-
el;
|
|
332
|
-
}, sx: {
|
|
248
|
+
return createPortal(_jsx(Box, { ref: setFloating, sx: {
|
|
333
249
|
pointerEvents: 'auto',
|
|
334
250
|
zIndex: 50,
|
|
335
251
|
position: strategy,
|
|
336
252
|
top: 0,
|
|
337
|
-
left:
|
|
253
|
+
left: editor._rootElement
|
|
338
254
|
? editor._rootElement.getBoundingClientRect().left + MARGIN_X
|
|
339
255
|
: 0,
|
|
340
|
-
transform:
|
|
341
|
-
|
|
342
|
-
: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,
|
|
343
|
-
width: fullWidth && editor._rootElement
|
|
256
|
+
transform: `translate3d(0, ${Math.round(y)}px, 0)`,
|
|
257
|
+
width: editor._rootElement
|
|
344
258
|
? editor._rootElement.getBoundingClientRect().width - MARGIN_X * 2
|
|
345
259
|
: '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);
|
|
260
|
+
}, children: _jsx(ChatInline, { selectedText: effectiveText, protocol: protocol, onReplaceSelection: handleReplaceSelection, onInsertInline: handleInsertInline, onInsertBelow: handleInsertBelow, onClose: onClose, onSaveSelection: saveSelection, onRestoreSelection: restoreSelection, pendingPrompt: pendingPrompt, onPendingPromptConsumed: onPendingPromptConsumed }) }), portalTarget);
|
|
378
261
|
}
|
|
379
262
|
export default ChatInlinePlugin;
|
package/lib/lexical/index.d.ts
CHANGED
|
@@ -4,3 +4,4 @@
|
|
|
4
4
|
* @module lexical
|
|
5
5
|
*/
|
|
6
6
|
export { ChatInlinePlugin, type ChatInlinePluginProps, SAVE_SELECTION_COMMAND, RESTORE_SELECTION_COMMAND, } from './ChatInlinePlugin';
|
|
7
|
+
export { useChatInlineToolbarItems, type ChatInlineToolbarOptions, type ChatInlineToolbarState, } from './useChatInlineToolbarItems';
|
package/lib/lexical/index.js
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
* Options for useChatInlineToolbarItems.
|
|
23
|
+
*/
|
|
24
|
+
export interface ChatInlineToolbarOptions {
|
|
25
|
+
/** When true the AI sparkle button is rendered in a disabled state. */
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Hook that creates ToolbarItem[] for AI actions in the floating toolbar.
|
|
30
|
+
*
|
|
31
|
+
* Returns toolbar items (divider + AI sparkle button) and
|
|
32
|
+
* state for controlling the ChatInline panel.
|
|
33
|
+
*/
|
|
34
|
+
export declare function useChatInlineToolbarItems(options?: ChatInlineToolbarOptions): ChatInlineToolbarState;
|
|
35
|
+
export default useChatInlineToolbarItems;
|
|
@@ -0,0 +1,91 @@
|
|
|
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 in the floating inline toolbar.
|
|
10
|
+
* Clicking the sparkle button directly opens the ChatInlinePlugin
|
|
11
|
+
* floating panel, where users can type free-form AI prompts.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const { toolbarItems, isAiOpen, pendingPrompt, clearPendingPrompt, closeAi } =
|
|
16
|
+
* useChatInlineToolbarItems();
|
|
17
|
+
*
|
|
18
|
+
* <FloatingTextFormatToolbarPlugin
|
|
19
|
+
* anchorElem={floatingAnchorElem}
|
|
20
|
+
* setIsLinkEditMode={setIsLinkEditMode}
|
|
21
|
+
* extraItems={toolbarItems}
|
|
22
|
+
* />
|
|
23
|
+
*
|
|
24
|
+
* <ChatInlinePlugin
|
|
25
|
+
* isOpen={isAiOpen}
|
|
26
|
+
* onClose={closeAi}
|
|
27
|
+
* pendingPrompt={pendingPrompt}
|
|
28
|
+
* onPendingPromptConsumed={clearPendingPrompt}
|
|
29
|
+
* />
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @module lexical/useChatInlineToolbarItems
|
|
33
|
+
*/
|
|
34
|
+
import { useState, useMemo, useCallback } from 'react';
|
|
35
|
+
import { SparkleFillIcon } from '@primer/octicons-react';
|
|
36
|
+
/**
|
|
37
|
+
* Hook that creates ToolbarItem[] for AI actions in the floating toolbar.
|
|
38
|
+
*
|
|
39
|
+
* Returns toolbar items (divider + AI sparkle button) and
|
|
40
|
+
* state for controlling the ChatInline panel.
|
|
41
|
+
*/
|
|
42
|
+
export function useChatInlineToolbarItems(options) {
|
|
43
|
+
const [isAiOpen, setIsAiOpen] = useState(false);
|
|
44
|
+
const [pendingPrompt, setPendingPrompt] = useState(null);
|
|
45
|
+
const openAi = useCallback(() => {
|
|
46
|
+
setIsAiOpen(true);
|
|
47
|
+
}, []);
|
|
48
|
+
const closeAi = useCallback(() => {
|
|
49
|
+
setIsAiOpen(false);
|
|
50
|
+
setPendingPrompt(null);
|
|
51
|
+
}, []);
|
|
52
|
+
const submitPrompt = useCallback((prompt) => {
|
|
53
|
+
setPendingPrompt(prompt);
|
|
54
|
+
setIsAiOpen(true);
|
|
55
|
+
}, []);
|
|
56
|
+
const clearPendingPrompt = useCallback(() => {
|
|
57
|
+
setPendingPrompt(null);
|
|
58
|
+
}, []);
|
|
59
|
+
const isDisabled = options?.disabled ?? false;
|
|
60
|
+
const toolbarItems = useMemo(() => {
|
|
61
|
+
return [
|
|
62
|
+
{
|
|
63
|
+
key: 'ai-divider',
|
|
64
|
+
type: 'divider',
|
|
65
|
+
order: 900,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
key: 'ai-actions',
|
|
69
|
+
type: 'button',
|
|
70
|
+
order: 901,
|
|
71
|
+
ariaLabel: 'AI Actions',
|
|
72
|
+
title: isDisabled
|
|
73
|
+
? 'Assign an agent to enable AI actions'
|
|
74
|
+
: 'AI Actions',
|
|
75
|
+
icon: SparkleFillIcon,
|
|
76
|
+
onClick: openAi,
|
|
77
|
+
disabled: isDisabled,
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
}, [openAi, isDisabled]);
|
|
81
|
+
return {
|
|
82
|
+
toolbarItems,
|
|
83
|
+
isAiOpen,
|
|
84
|
+
submitPrompt,
|
|
85
|
+
pendingPrompt,
|
|
86
|
+
clearPendingPrompt,
|
|
87
|
+
openAi,
|
|
88
|
+
closeAi,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
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
|
*
|