@datalayer/agent-runtimes 0.0.10 → 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 (138) 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 +33 -21
  15. package/lib/components/AgentConfiguration.js +76 -21
  16. package/lib/components/chat/components/AgentDetails.d.ts +3 -1
  17. package/lib/components/chat/components/AgentDetails.js +164 -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/ContextDistribution.js +2 -2
  29. package/lib/components/chat/components/ContextInspector.js +4 -2
  30. package/lib/components/chat/components/ContextPanel.js +1 -6
  31. package/lib/components/chat/components/base/ChatBase.d.ts +49 -8
  32. package/lib/components/chat/components/base/ChatBase.js +544 -149
  33. package/lib/components/chat/components/base/InputPrompt.d.ts +42 -0
  34. package/lib/components/chat/components/base/InputPrompt.js +131 -0
  35. package/lib/components/chat/components/index.d.ts +3 -3
  36. package/lib/components/chat/components/index.js +1 -1
  37. package/lib/components/chat/components/parts/ReasoningPart.js +2 -4
  38. package/lib/components/chat/components/parts/TextPart.js +2 -70
  39. package/lib/components/chat/components/styles/streamdownStyles.d.ts +23 -0
  40. package/lib/components/chat/components/styles/streamdownStyles.js +319 -0
  41. package/lib/components/chat/index.d.ts +1 -1
  42. package/lib/components/chat/index.js +1 -1
  43. package/lib/components/chat/inference/DatalayerInferenceProvider.js +16 -12
  44. package/lib/components/chat/inference/SelfHostedInferenceProvider.js +16 -12
  45. package/lib/components/chat/protocols/AGUIAdapter.d.ts +10 -3
  46. package/lib/components/chat/protocols/AGUIAdapter.js +123 -44
  47. package/lib/components/chat/types/tool.d.ts +5 -2
  48. package/lib/components/index.d.ts +2 -19
  49. package/lib/components/index.js +1 -10
  50. package/lib/config/index.d.ts +0 -3
  51. package/lib/config/index.js +0 -3
  52. package/lib/examples/A2UiRestaurantExample.js +1 -1
  53. package/lib/examples/AgentRuntimeChatExample.d.ts +15 -0
  54. package/lib/examples/AgentRuntimeChatExample.js +126 -0
  55. package/lib/examples/{AgentSpaceFormExample.d.ts → AgentRuntimeFormExample.d.ts} +3 -3
  56. package/lib/examples/{AgentSpaceFormExample.js → AgentRuntimeFormExample.js} +61 -17
  57. package/lib/examples/AgentRuntimeLexicalExample.js +6 -3
  58. package/lib/examples/AgentRuntimeLexicalSidebarExample.js +8 -1
  59. package/lib/examples/AgentRuntimeNotebookExample.js +6 -5
  60. package/lib/examples/CopilotKitNotebookExample.js +2 -2
  61. package/lib/examples/JupyterNotebookExample.js +2 -2
  62. package/lib/{components → examples/components}/Header.d.ts +2 -1
  63. package/lib/{components → examples/components}/HeaderControls.js +1 -1
  64. package/lib/{components → examples/components}/LexicalEditor.d.ts +6 -1
  65. package/lib/{components → examples/components}/LexicalEditor.js +4 -4
  66. package/lib/{components → examples/components}/MainContent.d.ts +1 -1
  67. package/lib/{components → examples/components}/MainContent.js +7 -5
  68. package/lib/examples/components/index.d.ts +16 -0
  69. package/lib/examples/components/index.js +13 -0
  70. package/lib/examples/example-selector.js +2 -1
  71. package/lib/examples/index.d.ts +1 -1
  72. package/lib/examples/index.js +1 -1
  73. package/lib/examples/main.js +2 -2
  74. package/lib/examples/stores/examplesStore.d.ts +2 -23
  75. package/lib/index.d.ts +2 -1
  76. package/lib/index.js +1 -0
  77. package/lib/lexical/ChatInlinePlugin.d.ts +13 -2
  78. package/lib/lexical/ChatInlinePlugin.js +41 -179
  79. package/lib/lexical/index.d.ts +1 -0
  80. package/lib/lexical/index.js +1 -0
  81. package/lib/lexical/useChatInlineToolbarItems.d.ts +28 -0
  82. package/lib/lexical/useChatInlineToolbarItems.js +163 -0
  83. package/lib/runtime/useAgentRuntime.d.ts +1 -1
  84. package/lib/runtime/useAgentRuntime.js +1 -1
  85. package/lib/specs/agents/codeai/agents.d.ts +28 -0
  86. package/lib/specs/agents/codeai/agents.js +151 -0
  87. package/lib/specs/agents/codeai/index.d.ts +1 -0
  88. package/lib/specs/agents/codeai/index.js +5 -0
  89. package/lib/{config → specs/agents/codemode-paper}/agents.d.ts +4 -6
  90. package/lib/specs/agents/codemode-paper/agents.js +308 -0
  91. package/lib/specs/agents/codemode-paper/index.d.ts +1 -0
  92. package/lib/specs/agents/codemode-paper/index.js +5 -0
  93. package/lib/specs/agents/datalayer-ai/agents.d.ts +31 -0
  94. package/lib/{config → specs/agents/datalayer-ai}/agents.js +42 -184
  95. package/lib/specs/agents/datalayer-ai/index.d.ts +1 -0
  96. package/lib/specs/agents/datalayer-ai/index.js +5 -0
  97. package/lib/specs/agents/index.d.ts +21 -0
  98. package/lib/specs/agents/index.js +47 -0
  99. package/lib/specs/envvars.d.ts +29 -0
  100. package/lib/specs/envvars.js +125 -0
  101. package/lib/specs/index.d.ts +5 -0
  102. package/lib/specs/index.js +9 -0
  103. package/lib/{config → specs}/mcpServers.d.ts +2 -1
  104. package/lib/{config → specs}/mcpServers.js +47 -1
  105. package/lib/specs/models.d.ts +68 -0
  106. package/lib/specs/models.js +239 -0
  107. package/lib/{config → specs}/skills.d.ts +2 -0
  108. package/lib/{config → specs}/skills.js +6 -0
  109. package/lib/state/substates/AIAgentState.d.ts +0 -1
  110. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.d.ts +11 -22
  111. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.js +5 -5
  112. package/lib/tools/adapters/agent-runtimes/lexicalHooks.d.ts +6 -6
  113. package/lib/tools/adapters/agent-runtimes/lexicalHooks.js +4 -4
  114. package/lib/tools/adapters/agent-runtimes/notebookHooks.d.ts +6 -6
  115. package/lib/tools/adapters/agent-runtimes/notebookHooks.js +4 -4
  116. package/lib/{types.d.ts → types/Types.d.ts} +42 -8
  117. package/lib/types/index.d.ts +1 -0
  118. package/lib/types/index.js +1 -0
  119. package/package.json +11 -5
  120. package/scripts/codegen/generate_agents.py +608 -157
  121. package/scripts/codegen/generate_envvars.py +302 -0
  122. package/scripts/codegen/generate_mcp_servers.py +33 -21
  123. package/scripts/codegen/generate_models.py +486 -0
  124. package/scripts/codegen/generate_skills.py +21 -8
  125. package/style/primer-primitives.css +22 -0
  126. package/lib/components/chat/components/elements/ChatInputPrompt.d.ts +0 -37
  127. package/lib/components/chat/components/elements/ChatInputPrompt.js +0 -150
  128. /package/lib/{components → examples/components}/FooterMetrics.d.ts +0 -0
  129. /package/lib/{components → examples/components}/FooterMetrics.js +0 -0
  130. /package/lib/{components → examples/components}/Header.js +0 -0
  131. /package/lib/{components → examples/components}/HeaderControls.d.ts +0 -0
  132. /package/lib/{components → examples/components}/MockFileBrowser.d.ts +0 -0
  133. /package/lib/{components → examples/components}/MockFileBrowser.js +0 -0
  134. /package/lib/{components → examples/components}/SessionTabs.d.ts +0 -0
  135. /package/lib/{components → examples/components}/SessionTabs.js +0 -0
  136. /package/lib/{components → examples/components}/TimeTravel.d.ts +0 -0
  137. /package/lib/{components → examples/components}/TimeTravel.js +0 -0
  138. /package/lib/{types.js → types/Types.js} +0 -0
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  [![Become a Sponsor](https://img.shields.io/static/v1?label=Become%20a%20Sponsor&message=%E2%9D%A4&logo=GitHub&style=flat&color=1ABC9C)](https://github.com/sponsors/datalayer)
10
10
 
11
- # 🤖 Agent Runtimes
11
+ # 🤖 🚀 Agent Runtimes
12
12
 
13
13
  [![Github Actions Status](https://github.com/datalayer/agent-runtimes/actions/workflows/build.yml/badge.svg)](https://github.com/datalayer/agent-runtimes/actions/workflows/build.yml)
14
14
  [![Netlify Status](https://api.netlify.com/api/v1/badges/f7f9e08a-884f-4f76-b20d-666d5873716c/deploy-status)](https://app.netlify.com/projects/agent-runtimes/deploys)
@@ -16,7 +16,7 @@
16
16
 
17
17
  **Agent Runtimes** is a unified platform for deploying, managing, and interacting with AI agents across multiple protocols and frameworks. It provides both a Python server for hosting agents and React components for seamless integration into web and desktop applications.
18
18
 
19
- ## 🎯 What is Agent Runtimes?
19
+ ## What is Agent Runtimes?
20
20
 
21
21
  Agent Runtimes solves the complexity of deploying AI agents by providing:
22
22
 
package/lib/Agent.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Agent
3
+ *
4
+ * Standalone chat interface served at /static/agent.html.
5
+ * Connects to the agent-runtimes AG-UI endpoint.
6
+ *
7
+ * The page is opened by codeai with a URL like:
8
+ * http://127.0.0.1:<port>/static/agent.html?agentId=<id>
9
+ *
10
+ * On mount it ensures the agent exists — creating it automatically
11
+ * if it doesn't — then renders the unified Chat component.
12
+ *
13
+ * Uses the unified Chat component which handles:
14
+ * - AG-UI protocol configuration
15
+ * - AgentDetails panel (via showInformation)
16
+ * - Conversation history persistence
17
+ * - Model/tools/skills selectors
18
+ * - Error and loading states
19
+ */
20
+ import React from 'react';
21
+ import '../style/primer-primitives.css';
22
+ /**
23
+ * Agent component — full-page chat interface.
24
+ *
25
+ * Reads the `agentId` query-string parameter, waits for the agent
26
+ * to be available, then renders the Chat.
27
+ */
28
+ export declare const Agent: React.FC;
29
+ export default Agent;
package/lib/Agent.js ADDED
@@ -0,0 +1,131 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * Agent
8
+ *
9
+ * Standalone chat interface served at /static/agent.html.
10
+ * Connects to the agent-runtimes AG-UI endpoint.
11
+ *
12
+ * The page is opened by codeai with a URL like:
13
+ * http://127.0.0.1:<port>/static/agent.html?agentId=<id>
14
+ *
15
+ * On mount it ensures the agent exists — creating it automatically
16
+ * if it doesn't — then renders the unified Chat component.
17
+ *
18
+ * Uses the unified Chat component which handles:
19
+ * - AG-UI protocol configuration
20
+ * - AgentDetails panel (via showInformation)
21
+ * - Conversation history persistence
22
+ * - Model/tools/skills selectors
23
+ * - Error and loading states
24
+ */
25
+ import { useEffect, useState } from 'react';
26
+ import { Text, Spinner } from '@primer/react';
27
+ import { AlertIcon } from '@primer/octicons-react';
28
+ import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
29
+ import { DatalayerThemeProvider } from '@datalayer/core';
30
+ import { Chat } from './components/chat';
31
+ import { DEFAULT_MODEL } from './specs';
32
+ import '../style/primer-primitives.css';
33
+ setupPrimerPortals();
34
+ const BASE_URL = window.location.origin;
35
+ function getAgentId() {
36
+ const params = new URLSearchParams(window.location.search);
37
+ return params.get('agentId') || 'default';
38
+ }
39
+ /**
40
+ * Agent component — full-page chat interface.
41
+ *
42
+ * Reads the `agentId` query-string parameter, waits for the agent
43
+ * to be available, then renders the Chat.
44
+ */
45
+ export const Agent = () => {
46
+ const [agentId] = useState(getAgentId);
47
+ const [isReady, setIsReady] = useState(false);
48
+ const [error, setError] = useState(null);
49
+ // Ensure the agent exists on mount — create it if it doesn't
50
+ useEffect(() => {
51
+ let cancelled = false;
52
+ const ensureAgent = async () => {
53
+ try {
54
+ // First check if the agent already exists
55
+ const getResp = await fetch(`${BASE_URL}/api/v1/agents/${encodeURIComponent(agentId)}`);
56
+ if (getResp.ok) {
57
+ if (!cancelled)
58
+ setIsReady(true);
59
+ return;
60
+ }
61
+ // Agent doesn't exist — create it
62
+ const createResp = await fetch(`${BASE_URL}/api/v1/agents`, {
63
+ method: 'POST',
64
+ headers: { 'Content-Type': 'application/json' },
65
+ body: JSON.stringify({
66
+ name: agentId,
67
+ description: 'Agent created by Agent page',
68
+ agent_library: 'pydantic-ai',
69
+ transport: 'ag-ui',
70
+ model: DEFAULT_MODEL,
71
+ system_prompt: 'You are a helpful AI assistant. You can help with code, explanations, and data analysis.',
72
+ }),
73
+ });
74
+ if (createResp.ok || createResp.status === 400) {
75
+ // 400 means agent already exists (race condition), which is fine
76
+ if (!cancelled)
77
+ setIsReady(true);
78
+ }
79
+ else {
80
+ const errorData = await createResp.json().catch(() => ({}));
81
+ throw new Error(errorData.detail || `Failed to create agent: ${createResp.status}`);
82
+ }
83
+ }
84
+ catch (err) {
85
+ if (!cancelled) {
86
+ setError(err instanceof Error ? err.message : 'Failed to reach agent');
87
+ }
88
+ }
89
+ };
90
+ ensureAgent();
91
+ return () => {
92
+ cancelled = true;
93
+ };
94
+ }, [agentId]);
95
+ // Loading state while verifying agent
96
+ if (!isReady && !error) {
97
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
98
+ display: 'flex',
99
+ flexDirection: 'column',
100
+ alignItems: 'center',
101
+ justifyContent: 'center',
102
+ height: '100vh',
103
+ gap: 3,
104
+ bg: 'canvas.default',
105
+ }, children: [_jsx(Spinner, { size: "large" }), _jsxs(Text, { sx: { color: 'fg.muted' }, children: ["Connecting to agent ", agentId, "..."] })] }) }));
106
+ }
107
+ // Error state
108
+ if (error) {
109
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
110
+ display: 'flex',
111
+ flexDirection: 'column',
112
+ alignItems: 'center',
113
+ justifyContent: 'center',
114
+ height: '100vh',
115
+ gap: 3,
116
+ bg: 'canvas.default',
117
+ }, children: [_jsx(AlertIcon, { size: 48 }), _jsx(Text, { sx: { color: 'danger.fg', fontSize: 2 }, children: "Failed to connect to agent" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: error })] }) }));
118
+ }
119
+ // Agent is ready — render the Chat component
120
+ return (_jsx(DatalayerThemeProvider, { children: _jsx(Chat, { transport: "ag-ui", baseUrl: BASE_URL, agentId: agentId, title: "Agent", placeholder: "Send a message...", description: "Chat with the agent", showHeader: true, height: '100vh', showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, showTokenUsage: true, showInformation: true, autoFocus: true, runtimeId: agentId, historyEndpoint: `${BASE_URL}/api/v1/history`, suggestions: [
121
+ {
122
+ title: 'Hello',
123
+ message: 'Hello, what can you do?',
124
+ },
125
+ {
126
+ title: 'Help',
127
+ message: 'What tools do you have available?',
128
+ },
129
+ ], submitOnSuggestionClick: true }) }));
130
+ };
131
+ export default Agent;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * AgentLexical
3
+ *
4
+ * Standalone Lexical editor + chat interface served at /static/agent-lexical.html.
5
+ * Connects to the agent-runtimes AG-UI endpoint and provides a Lexical
6
+ * rich-text editor alongside the Chat component with lexical tools registered.
7
+ *
8
+ * The page is opened by codeai with a URL like:
9
+ * http://127.0.0.1:<port>/static/agent-lexical.html?agentId=<id>
10
+ *
11
+ * Query parameters:
12
+ * - agentId: the agent identifier (required, set by codeai)
13
+ * - jupyterBaseUrl: base URL for the Jupyter server (optional, falls back to jupyter-config-data)
14
+ * - jupyterToken: token for the Jupyter server (optional, falls back to jupyter-config-data)
15
+ */
16
+ import 'prismjs';
17
+ import 'prismjs/components/prism-clike';
18
+ import 'prismjs/components/prism-javascript';
19
+ import 'prismjs/components/prism-markup';
20
+ import 'prismjs/components/prism-markdown';
21
+ import 'prismjs/components/prism-c';
22
+ import 'prismjs/components/prism-css';
23
+ import 'prismjs/components/prism-objectivec';
24
+ import 'prismjs/components/prism-sql';
25
+ import 'prismjs/components/prism-python';
26
+ import 'prismjs/components/prism-rust';
27
+ import 'prismjs/components/prism-swift';
28
+ import React from 'react';
29
+ import '@datalayer/jupyter-lexical/style/index.css';
30
+ import './examples/lexical/lexical-theme.css';
31
+ import '@datalayer/jupyter-lexical/style/modal-overrides.css';
32
+ import '../style/primer-primitives.css';
33
+ export declare const AgentLexical: React.FC;
34
+ export default AgentLexical;
@@ -0,0 +1,296 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * AgentLexical
8
+ *
9
+ * Standalone Lexical editor + chat interface served at /static/agent-lexical.html.
10
+ * Connects to the agent-runtimes AG-UI endpoint and provides a Lexical
11
+ * rich-text editor alongside the Chat component with lexical tools registered.
12
+ *
13
+ * The page is opened by codeai with a URL like:
14
+ * http://127.0.0.1:<port>/static/agent-lexical.html?agentId=<id>
15
+ *
16
+ * Query parameters:
17
+ * - agentId: the agent identifier (required, set by codeai)
18
+ * - jupyterBaseUrl: base URL for the Jupyter server (optional, falls back to jupyter-config-data)
19
+ * - jupyterToken: token for the Jupyter server (optional, falls back to jupyter-config-data)
20
+ */
21
+ import 'prismjs';
22
+ import 'prismjs/components/prism-clike';
23
+ import 'prismjs/components/prism-javascript';
24
+ import 'prismjs/components/prism-markup';
25
+ import 'prismjs/components/prism-markdown';
26
+ import 'prismjs/components/prism-c';
27
+ import 'prismjs/components/prism-css';
28
+ import 'prismjs/components/prism-objectivec';
29
+ import 'prismjs/components/prism-sql';
30
+ import 'prismjs/components/prism-python';
31
+ import 'prismjs/components/prism-rust';
32
+ import 'prismjs/components/prism-swift';
33
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
34
+ import { $getRoot, $createParagraphNode } from 'lexical';
35
+ import { LexicalComposer } from '@lexical/react/LexicalComposer';
36
+ import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
37
+ import { ContentEditable } from '@lexical/react/LexicalContentEditable';
38
+ import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
39
+ import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
40
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
41
+ import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
42
+ import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin';
43
+ import { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin';
44
+ import { TRANSFORMERS } from '@lexical/markdown';
45
+ import { registerCodeHighlighting } from '@lexical/code';
46
+ import { ListPlugin } from '@lexical/react/LexicalListPlugin';
47
+ import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
48
+ import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
49
+ import { Text, Spinner } from '@primer/react';
50
+ import { AlertIcon } from '@primer/octicons-react';
51
+ import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
52
+ import { DatalayerThemeProvider } from '@datalayer/core';
53
+ import { JupyterReactTheme, loadJupyterConfig, createServerSettings, getJupyterServerUrl, getJupyterServerToken, setJupyterServerUrl, setJupyterServerToken, useJupyter, } from '@datalayer/jupyter-react';
54
+ import { ComponentPickerMenuPlugin, JupyterCellPlugin, JupyterInputOutputPlugin, DraggableBlockPlugin, ImagesPlugin, HorizontalRulePlugin, EquationsPlugin, YouTubePlugin, ExcalidrawPlugin, CollapsiblePlugin, AutoLinkPlugin, AutoEmbedPlugin, LexicalConfigProvider, LexicalStatePlugin, FloatingTextFormatToolbarPlugin, CodeActionMenuPlugin, ListMaxIndentLevelPlugin, TableCellResizerPlugin, TablePlugin, } from '@datalayer/jupyter-lexical';
55
+ import { ServiceManager } from '@jupyterlab/services';
56
+ import { Chat } from './components/chat';
57
+ import { ChatInlinePlugin } from './lexical/ChatInlinePlugin';
58
+ import { useChatInlineToolbarItems } from './lexical/useChatInlineToolbarItems';
59
+ import { useLexicalTools } from './tools/adapters/agent-runtimes/lexicalHooks';
60
+ import { editorConfig } from './examples/lexical/editorConfig';
61
+ import { DEFAULT_MODEL } from './specs';
62
+ import '@datalayer/jupyter-lexical/style/index.css';
63
+ import './examples/lexical/lexical-theme.css';
64
+ import '@datalayer/jupyter-lexical/style/modal-overrides.css';
65
+ import '../style/primer-primitives.css';
66
+ setupPrimerPortals();
67
+ const BASE_URL = window.location.origin;
68
+ const LEXICAL_ID = 'agent-lexical';
69
+ function getQueryParam(name) {
70
+ return new URLSearchParams(window.location.search).get(name);
71
+ }
72
+ function getAgentId() {
73
+ return getQueryParam('agentId') || 'default';
74
+ }
75
+ /**
76
+ * Initialise Jupyter configuration.
77
+ *
78
+ * Priority:
79
+ * 1. Query parameters (jupyterBaseUrl / jupyterToken)
80
+ * 2. <script id="jupyter-config-data"> block in the HTML page
81
+ */
82
+ function initJupyterConfig() {
83
+ loadJupyterConfig();
84
+ const qBaseUrl = getQueryParam('jupyterBaseUrl');
85
+ const qToken = getQueryParam('jupyterToken');
86
+ if (qBaseUrl)
87
+ setJupyterServerUrl(qBaseUrl);
88
+ if (qToken)
89
+ setJupyterServerToken(qToken);
90
+ const el = document.getElementById('jupyter-config-data');
91
+ if (el?.textContent) {
92
+ try {
93
+ const cfg = JSON.parse(el.textContent);
94
+ if (!qBaseUrl && cfg.baseUrl)
95
+ setJupyterServerUrl(cfg.baseUrl);
96
+ if (!qToken && cfg.token)
97
+ setJupyterServerToken(cfg.token);
98
+ }
99
+ catch {
100
+ // ignore
101
+ }
102
+ }
103
+ }
104
+ // ─── Lexical plugins ────────────────────────────────────────────────────────
105
+ /**
106
+ * Lexical plugin for loading initial content into the editor.
107
+ */
108
+ function LoadContentPlugin({ content }) {
109
+ const [editor] = useLexicalComposerContext();
110
+ const isFirstRender = useRef(true);
111
+ useEffect(() => {
112
+ if (!content || !isFirstRender.current) {
113
+ return;
114
+ }
115
+ isFirstRender.current = false;
116
+ try {
117
+ const parsed = JSON.parse(content);
118
+ if (parsed && typeof parsed === 'object' && parsed.root) {
119
+ const editorState = editor.parseEditorState(content);
120
+ editor.setEditorState(editorState, { tag: 'history-merge' });
121
+ }
122
+ else {
123
+ throw new Error('Invalid Lexical editor state format');
124
+ }
125
+ }
126
+ catch {
127
+ editor.update(() => {
128
+ const root = $getRoot();
129
+ root.clear();
130
+ const paragraph = $createParagraphNode();
131
+ root.append(paragraph);
132
+ }, { tag: 'history-merge' });
133
+ }
134
+ }, [content, editor]);
135
+ return null;
136
+ }
137
+ function CodeHighlightPlugin() {
138
+ const [editor] = useLexicalComposerContext();
139
+ useEffect(() => {
140
+ return registerCodeHighlighting(editor);
141
+ }, [editor]);
142
+ return null;
143
+ }
144
+ function KernelPluginsInner() {
145
+ const { defaultKernel } = useJupyter();
146
+ return (_jsxs(_Fragment, { children: [_jsx(ComponentPickerMenuPlugin, { kernel: defaultKernel }), _jsx(JupyterInputOutputPlugin, { kernel: defaultKernel })] }));
147
+ }
148
+ /**
149
+ * Plugin that captures lexical tools and passes them to parent.
150
+ * Must be rendered inside LexicalConfigProvider context.
151
+ */
152
+ function LexicalToolsPlugin({ onToolsReady, }) {
153
+ const tools = useLexicalTools(LEXICAL_ID);
154
+ useEffect(() => {
155
+ onToolsReady(tools);
156
+ }, [tools, onToolsReady]);
157
+ return null;
158
+ }
159
+ const LexicalPanel = React.memo(function LexicalPanel({ serviceManager, onToolsReady, }) {
160
+ const [floatingAnchorElem, setFloatingAnchorElem] = useState(null);
161
+ const [_isLinkEditMode, setIsLinkEditMode] = useState(false);
162
+ const { toolbarItems, isAiOpen, pendingPrompt, clearPendingPrompt, closeAi } = useChatInlineToolbarItems();
163
+ const onRef = (_floatingAnchorElem) => {
164
+ if (_floatingAnchorElem !== null) {
165
+ setFloatingAnchorElem(_floatingAnchorElem);
166
+ }
167
+ };
168
+ const handleChange = useCallback((_editorState) => {
169
+ // onChange handler
170
+ }, []);
171
+ const agentId = getAgentId();
172
+ const agUiEndpoint = `${BASE_URL}/api/v1/ag-ui/${encodeURIComponent(agentId)}/`;
173
+ return (_jsx(Box, { sx: {
174
+ flex: 1,
175
+ display: 'flex',
176
+ flexDirection: 'column',
177
+ overflow: 'auto',
178
+ borderRight: '1px solid',
179
+ borderColor: 'border.default',
180
+ }, children: _jsx(Box, { sx: { padding: 3 }, children: _jsxs(LexicalConfigProvider, { lexicalId: LEXICAL_ID, serviceManager: serviceManager, children: [_jsx(LexicalToolsPlugin, { onToolsReady: onToolsReady }), _jsx(LexicalComposer, { initialConfig: editorConfig, children: _jsxs("div", { className: "lexical-editor-inner", ref: onRef, children: [_jsx(LexicalStatePlugin, {}), _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "lexical-editor-content", "aria-label": "Lexical Editor" }), ErrorBoundary: LexicalErrorBoundary }), _jsx(OnChangePlugin, { onChange: handleChange }), _jsx(HistoryPlugin, {}), _jsx(AutoFocusPlugin, {}), _jsx(ListPlugin, {}), _jsx(CheckListPlugin, {}), _jsx(LinkPlugin, {}), _jsx(AutoLinkPlugin, {}), _jsx(ListMaxIndentLevelPlugin, { maxDepth: 7 }), _jsx(MarkdownShortcutPlugin, { transformers: TRANSFORMERS }), _jsx(LoadContentPlugin, {}), _jsx(CodeHighlightPlugin, {}), _jsx(ImagesPlugin, { captionsEnabled: false }), _jsx(HorizontalRulePlugin, {}), _jsx(EquationsPlugin, {}), _jsx(YouTubePlugin, {}), _jsx(ExcalidrawPlugin, {}), _jsx(CollapsiblePlugin, {}), _jsx(AutoEmbedPlugin, {}), _jsx(TablePlugin, {}), _jsx(TableCellResizerPlugin, {}), _jsx(JupyterCellPlugin, {}), _jsx(JupyterReactTheme, { children: _jsx(KernelPluginsInner, {}) }), floatingAnchorElem && (_jsxs(_Fragment, { children: [_jsx(DraggableBlockPlugin, { anchorElem: floatingAnchorElem }), _jsx(FloatingTextFormatToolbarPlugin, { anchorElem: floatingAnchorElem, setIsLinkEditMode: setIsLinkEditMode, extraItems: toolbarItems }), _jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem })] })), _jsx(ChatInlinePlugin, { protocol: {
181
+ type: 'ag-ui',
182
+ endpoint: agUiEndpoint,
183
+ }, isOpen: isAiOpen, onClose: closeAi, pendingPrompt: pendingPrompt, onPendingPromptConsumed: clearPendingPrompt })] }) })] }) }) }));
184
+ });
185
+ const ChatPanel = ({ agentId, tools }) => {
186
+ return (_jsx(Box, { sx: {
187
+ width: '420px',
188
+ minWidth: '320px',
189
+ display: 'flex',
190
+ flexDirection: 'column',
191
+ overflow: 'hidden',
192
+ }, children: _jsx(Chat, { transport: "ag-ui", baseUrl: BASE_URL, agentId: agentId, title: "Agent Lexical", placeholder: "Ask about the document...", description: "Chat with the agent to manipulate the document", showHeader: true, height: "100vh", showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, showTokenUsage: true, showInformation: true, frontendTools: tools, autoFocus: true, runtimeId: agentId, historyEndpoint: `${BASE_URL}/api/v1/history`, suggestions: [
193
+ {
194
+ title: 'Insert heading',
195
+ message: 'Insert a heading that says "Welcome"',
196
+ },
197
+ {
198
+ title: 'Add code block',
199
+ message: 'Add a Python code block with a hello world example',
200
+ },
201
+ {
202
+ title: 'Create list',
203
+ message: 'Create a bullet list with three items about Jupyter',
204
+ },
205
+ ], submitOnSuggestionClick: true }) }));
206
+ };
207
+ // ─── Main component ─────────────────────────────────────────────────────────
208
+ export const AgentLexical = () => {
209
+ const [agentId] = useState(getAgentId);
210
+ const [isReady, setIsReady] = useState(false);
211
+ const [error, setError] = useState(null);
212
+ const [serviceManager, setServiceManager] = useState(null);
213
+ const [tools, setTools] = useState([]);
214
+ const handleToolsReady = useCallback((newTools) => {
215
+ setTools(newTools);
216
+ }, []);
217
+ // Verify the agent exists AND initialise the Jupyter service manager
218
+ useEffect(() => {
219
+ let cancelled = false;
220
+ const init = async () => {
221
+ try {
222
+ // 1. Ensure agent exists — create if missing
223
+ const getResp = await fetch(`${BASE_URL}/api/v1/agents/${encodeURIComponent(agentId)}`);
224
+ if (!getResp.ok) {
225
+ const createResp = await fetch(`${BASE_URL}/api/v1/agents`, {
226
+ method: 'POST',
227
+ headers: { 'Content-Type': 'application/json' },
228
+ body: JSON.stringify({
229
+ name: agentId,
230
+ description: 'Agent created by Agent Lexical page',
231
+ agent_library: 'pydantic-ai',
232
+ transport: 'ag-ui',
233
+ model: DEFAULT_MODEL,
234
+ system_prompt: 'You are a helpful AI assistant that helps users work with documents. You can help with writing, editing, and formatting content.',
235
+ }),
236
+ });
237
+ if (!createResp.ok && createResp.status !== 400) {
238
+ const d = await createResp.json().catch(() => ({}));
239
+ throw new Error(d.detail || `Failed to create agent: ${createResp.status}`);
240
+ }
241
+ }
242
+ // 2. Initialise Jupyter
243
+ initJupyterConfig();
244
+ const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken());
245
+ const manager = new ServiceManager({ serverSettings });
246
+ await manager.ready;
247
+ if (!cancelled) {
248
+ setServiceManager(manager);
249
+ setIsReady(true);
250
+ }
251
+ }
252
+ catch (err) {
253
+ if (!cancelled) {
254
+ setError(err instanceof Error ? err.message : 'Failed to initialise');
255
+ }
256
+ }
257
+ };
258
+ init();
259
+ return () => {
260
+ cancelled = true;
261
+ };
262
+ }, [agentId]);
263
+ // Loading
264
+ if (!isReady && !error) {
265
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
266
+ display: 'flex',
267
+ flexDirection: 'column',
268
+ alignItems: 'center',
269
+ justifyContent: 'center',
270
+ height: '100vh',
271
+ gap: 3,
272
+ bg: 'canvas.default',
273
+ }, children: [_jsx(Spinner, { size: "large" }), _jsxs(Text, { sx: { color: 'fg.muted' }, children: ["Connecting to agent ", agentId, "\u2026"] })] }) }));
274
+ }
275
+ // Error
276
+ if (error) {
277
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
278
+ display: 'flex',
279
+ flexDirection: 'column',
280
+ alignItems: 'center',
281
+ justifyContent: 'center',
282
+ height: '100vh',
283
+ gap: 3,
284
+ bg: 'canvas.default',
285
+ }, children: [_jsx(AlertIcon, { size: 48 }), _jsx(Text, { sx: { color: 'danger.fg', fontSize: 2 }, children: "Failed to connect" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: error })] }) }));
286
+ }
287
+ // Ready — lexical editor + chat side-by-side
288
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
289
+ display: 'flex',
290
+ height: '100vh',
291
+ width: '100vw',
292
+ overflow: 'hidden',
293
+ bg: 'canvas.default',
294
+ }, children: [serviceManager && (_jsx(LexicalPanel, { serviceManager: serviceManager, onToolsReady: handleToolsReady })), _jsx(ChatPanel, { agentId: agentId, tools: tools })] }) }));
295
+ };
296
+ export default AgentLexical;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * AgentNotebook
3
+ *
4
+ * Standalone notebook + chat interface served at /static/agent-notebook.html.
5
+ * Connects to the agent-runtimes AG-UI endpoint and provides a Jupyter
6
+ * notebook alongside the Chat component with notebook tools registered.
7
+ *
8
+ * The page is opened by codeai with a URL like:
9
+ * http://127.0.0.1:<port>/static/agent-notebook.html?agentId=<id>
10
+ *
11
+ * Query parameters:
12
+ * - agentId: the agent identifier (required, set by codeai)
13
+ * - jupyterBaseUrl: base URL for the Jupyter server (optional, falls back to jupyter-config-data)
14
+ * - jupyterToken: token for the Jupyter server (optional, falls back to jupyter-config-data)
15
+ */
16
+ import React from 'react';
17
+ import '../style/primer-primitives.css';
18
+ export declare const AgentNotebook: React.FC;
19
+ export default AgentNotebook;