@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.
Files changed (136) hide show
  1. package/README.md +2 -2
  2. package/lib/Agent.d.ts +29 -0
  3. package/lib/Agent.js +131 -0
  4. package/lib/AgentLexical.d.ts +34 -0
  5. package/lib/AgentLexical.js +296 -0
  6. package/lib/AgentNotebook.d.ts +19 -0
  7. package/lib/AgentNotebook.js +192 -0
  8. package/lib/agent-lexical-main.d.ts +1 -0
  9. package/lib/agent-lexical-main.js +11 -0
  10. package/lib/agent-main.d.ts +1 -0
  11. package/lib/agent-main.js +11 -0
  12. package/lib/agent-notebook-main.d.ts +1 -0
  13. package/lib/agent-notebook-main.js +12 -0
  14. package/lib/components/AgentConfiguration.d.ts +4 -22
  15. package/lib/components/AgentConfiguration.js +8 -8
  16. package/lib/components/chat/components/AgentDetails.d.ts +3 -1
  17. package/lib/components/chat/components/AgentDetails.js +6 -6
  18. package/lib/components/chat/components/Chat.d.ts +29 -3
  19. package/lib/components/chat/components/Chat.js +64 -59
  20. package/lib/components/chat/components/ChatFloating.d.ts +34 -12
  21. package/lib/components/chat/components/ChatFloating.js +54 -21
  22. package/lib/components/chat/components/ChatInline.d.ts +5 -1
  23. package/lib/components/chat/components/ChatInline.js +8 -1
  24. package/lib/components/chat/components/ChatSidebar.d.ts +6 -1
  25. package/lib/components/chat/components/ChatSidebar.js +2 -2
  26. package/lib/components/chat/components/ChatStandalone.d.ts +6 -1
  27. package/lib/components/chat/components/ChatStandalone.js +2 -2
  28. package/lib/components/chat/components/base/ChatBase.d.ts +49 -8
  29. package/lib/components/chat/components/base/ChatBase.js +544 -149
  30. package/lib/components/chat/components/base/InputPrompt.d.ts +42 -0
  31. package/lib/components/chat/components/base/InputPrompt.js +131 -0
  32. package/lib/components/chat/components/index.d.ts +3 -3
  33. package/lib/components/chat/components/index.js +1 -1
  34. package/lib/components/chat/components/parts/ReasoningPart.js +2 -4
  35. package/lib/components/chat/components/parts/TextPart.js +2 -70
  36. package/lib/components/chat/components/styles/streamdownStyles.d.ts +23 -0
  37. package/lib/components/chat/components/styles/streamdownStyles.js +319 -0
  38. package/lib/components/chat/index.d.ts +1 -1
  39. package/lib/components/chat/index.js +1 -1
  40. package/lib/components/chat/inference/DatalayerInferenceProvider.js +16 -12
  41. package/lib/components/chat/inference/SelfHostedInferenceProvider.js +16 -12
  42. package/lib/components/chat/protocols/AGUIAdapter.d.ts +10 -3
  43. package/lib/components/chat/protocols/AGUIAdapter.js +123 -44
  44. package/lib/components/chat/types/tool.d.ts +5 -2
  45. package/lib/components/index.d.ts +1 -18
  46. package/lib/components/index.js +0 -9
  47. package/lib/config/index.d.ts +0 -4
  48. package/lib/config/index.js +0 -4
  49. package/lib/examples/A2UiRestaurantExample.js +1 -1
  50. package/lib/examples/AgentRuntimeChatExample.d.ts +15 -0
  51. package/lib/examples/AgentRuntimeChatExample.js +126 -0
  52. package/lib/examples/{AgentSpaceFormExample.d.ts → AgentRuntimeFormExample.d.ts} +3 -3
  53. package/lib/examples/{AgentSpaceFormExample.js → AgentRuntimeFormExample.js} +10 -8
  54. package/lib/examples/AgentRuntimeLexicalExample.js +6 -3
  55. package/lib/examples/AgentRuntimeLexicalSidebarExample.js +8 -1
  56. package/lib/examples/AgentRuntimeNotebookExample.js +6 -5
  57. package/lib/examples/CopilotKitNotebookExample.js +2 -2
  58. package/lib/examples/JupyterNotebookExample.js +2 -2
  59. package/lib/{components → examples/components}/Header.d.ts +2 -1
  60. package/lib/{components → examples/components}/HeaderControls.js +1 -1
  61. package/lib/{components → examples/components}/LexicalEditor.d.ts +6 -1
  62. package/lib/{components → examples/components}/LexicalEditor.js +4 -4
  63. package/lib/{components → examples/components}/MainContent.d.ts +1 -1
  64. package/lib/{components → examples/components}/MainContent.js +7 -5
  65. package/lib/examples/components/index.d.ts +16 -0
  66. package/lib/examples/components/index.js +13 -0
  67. package/lib/examples/example-selector.js +2 -1
  68. package/lib/examples/index.d.ts +1 -1
  69. package/lib/examples/index.js +1 -1
  70. package/lib/examples/main.js +2 -2
  71. package/lib/examples/stores/examplesStore.d.ts +2 -23
  72. package/lib/index.d.ts +2 -1
  73. package/lib/index.js +1 -0
  74. package/lib/lexical/ChatInlinePlugin.d.ts +13 -2
  75. package/lib/lexical/ChatInlinePlugin.js +41 -179
  76. package/lib/lexical/index.d.ts +1 -0
  77. package/lib/lexical/index.js +1 -0
  78. package/lib/lexical/useChatInlineToolbarItems.d.ts +28 -0
  79. package/lib/lexical/useChatInlineToolbarItems.js +163 -0
  80. package/lib/runtime/useAgentRuntime.d.ts +1 -1
  81. package/lib/runtime/useAgentRuntime.js +1 -1
  82. package/lib/{config/agents/code-ai → specs/agents/codeai}/agents.d.ts +5 -2
  83. package/lib/specs/agents/codeai/agents.js +151 -0
  84. package/lib/{config → specs}/agents/codemode-paper/agents.d.ts +4 -2
  85. package/lib/{config → specs}/agents/codemode-paper/agents.js +39 -19
  86. package/lib/{config → specs}/agents/datalayer-ai/agents.d.ts +4 -2
  87. package/lib/{config → specs}/agents/datalayer-ai/agents.js +17 -2
  88. package/lib/{config → specs}/agents/index.d.ts +3 -1
  89. package/lib/{config → specs}/agents/index.js +12 -3
  90. package/lib/{config → specs}/envvars.d.ts +1 -0
  91. package/lib/{config → specs}/envvars.js +10 -0
  92. package/lib/specs/index.d.ts +5 -0
  93. package/lib/specs/index.js +9 -0
  94. package/lib/{config → specs}/mcpServers.d.ts +2 -1
  95. package/lib/{config → specs}/mcpServers.js +23 -1
  96. package/lib/specs/models.d.ts +68 -0
  97. package/lib/specs/models.js +239 -0
  98. package/lib/state/substates/AIAgentState.d.ts +0 -1
  99. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.d.ts +11 -22
  100. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.js +5 -5
  101. package/lib/tools/adapters/agent-runtimes/lexicalHooks.d.ts +6 -6
  102. package/lib/tools/adapters/agent-runtimes/lexicalHooks.js +4 -4
  103. package/lib/tools/adapters/agent-runtimes/notebookHooks.d.ts +6 -6
  104. package/lib/tools/adapters/agent-runtimes/notebookHooks.js +4 -4
  105. package/lib/{types.d.ts → types/Types.d.ts} +32 -6
  106. package/lib/types/index.d.ts +1 -0
  107. package/lib/types/index.js +1 -0
  108. package/package.json +11 -5
  109. package/scripts/codegen/generate_agents.py +53 -13
  110. package/scripts/codegen/generate_envvars.py +1 -1
  111. package/scripts/codegen/generate_mcp_servers.py +5 -5
  112. package/scripts/codegen/generate_models.py +486 -0
  113. package/scripts/codegen/generate_skills.py +2 -2
  114. package/style/primer-primitives.css +22 -0
  115. package/lib/components/chat/components/elements/ChatInputPrompt.d.ts +0 -37
  116. package/lib/components/chat/components/elements/ChatInputPrompt.js +0 -150
  117. package/lib/config/agents/code-ai/agents.js +0 -70
  118. /package/lib/{components → examples/components}/FooterMetrics.d.ts +0 -0
  119. /package/lib/{components → examples/components}/FooterMetrics.js +0 -0
  120. /package/lib/{components → examples/components}/Header.js +0 -0
  121. /package/lib/{components → examples/components}/HeaderControls.d.ts +0 -0
  122. /package/lib/{components → examples/components}/MockFileBrowser.d.ts +0 -0
  123. /package/lib/{components → examples/components}/MockFileBrowser.js +0 -0
  124. /package/lib/{components → examples/components}/SessionTabs.d.ts +0 -0
  125. /package/lib/{components → examples/components}/SessionTabs.js +0 -0
  126. /package/lib/{components → examples/components}/TimeTravel.d.ts +0 -0
  127. /package/lib/{components → examples/components}/TimeTravel.js +0 -0
  128. /package/lib/{config/agents/code-ai → specs/agents/codeai}/index.d.ts +0 -0
  129. /package/lib/{config/agents/code-ai → specs/agents/codeai}/index.js +0 -0
  130. /package/lib/{config → specs}/agents/codemode-paper/index.d.ts +0 -0
  131. /package/lib/{config → specs}/agents/codemode-paper/index.js +0 -0
  132. /package/lib/{config → specs}/agents/datalayer-ai/index.d.ts +0 -0
  133. /package/lib/{config → specs}/agents/datalayer-ai/index.js +0 -0
  134. /package/lib/{config → specs}/skills.d.ts +0 -0
  135. /package/lib/{config → specs}/skills.js +0 -0
  136. /package/lib/{types.js → types/Types.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
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 text is selected
10
- * in the Lexical editor. It provides AI-powered text manipulation features
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
- * Features:
14
- * - Detects text selection in the editor
15
- * - Shows floating ChatInline component near the selection
16
- * - Supports custom prompts and pre-defined AI actions
17
- * - Can replace selection, insert inline, or insert below
18
- * - Uses floating-ui for positioning
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, FORMAT_TEXT_COMMAND, } from 'lexical';
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, IconButton } from '@primer/react';
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
- * Hook to detect if mouse is pressed outside a specific element (for drag selection detection)
149
- * Returns true only when mouse is down AND the click started outside the provided element
150
- */
151
- function useIsMouseDownOutside(getElement) {
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, x, y, } = useFloating({
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
- // Handle close
302
- const handleClose = useCallback(() => {
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(_jsxs(Box, { ref: (el) => {
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: fullWidth && editor._rootElement
232
+ left: editor._rootElement
338
233
  ? editor._rootElement.getBoundingClientRect().left + MARGIN_X
339
234
  : 0,
340
- transform: fullWidth
341
- ? `translate3d(0, ${Math.round(y)}px, 0)`
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
- minWidth: fullWidth ? undefined : 'max-content',
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;
@@ -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 ChatInlineToolbarState, } from './useChatInlineToolbarItems';
@@ -8,3 +8,4 @@
8
8
  * @module lexical
9
9
  */
10
10
  export { ChatInlinePlugin, SAVE_SELECTION_COMMAND, RESTORE_SELECTION_COMMAND, } from './ChatInlinePlugin';
11
+ export { useChatInlineToolbarItems, } from './useChatInlineToolbarItems';
@@ -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} tools={tools} />
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} tools={tools} />
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
  *