@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
@@ -0,0 +1,192 @@
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
+ * AgentNotebook
8
+ *
9
+ * Standalone notebook + chat interface served at /static/agent-notebook.html.
10
+ * Connects to the agent-runtimes AG-UI endpoint and provides a Jupyter
11
+ * notebook alongside the Chat component with notebook tools registered.
12
+ *
13
+ * The page is opened by codeai with a URL like:
14
+ * http://127.0.0.1:<port>/static/agent-notebook.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 { useEffect, useState } from 'react';
22
+ import { Text, Spinner } from '@primer/react';
23
+ import { AlertIcon } from '@primer/octicons-react';
24
+ import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
25
+ import { DatalayerThemeProvider } from '@datalayer/core';
26
+ import { Notebook, JupyterReactTheme, loadJupyterConfig, createServerSettings, getJupyterServerUrl, getJupyterServerToken, setJupyterServerUrl, setJupyterServerToken, } from '@datalayer/jupyter-react';
27
+ import { ServiceManager } from '@jupyterlab/services';
28
+ import { Chat } from './components/chat';
29
+ import { useNotebookTools } from './tools/adapters/agent-runtimes/notebookHooks';
30
+ import { DEFAULT_MODEL } from './specs';
31
+ import MatplotlibNotebook from './examples/stores/notebooks/Matplotlib.ipynb.json';
32
+ import '../style/primer-primitives.css';
33
+ setupPrimerPortals();
34
+ const BASE_URL = window.location.origin;
35
+ const NOTEBOOK_ID = 'agent-notebook';
36
+ function getQueryParam(name) {
37
+ return new URLSearchParams(window.location.search).get(name);
38
+ }
39
+ function getAgentId() {
40
+ return getQueryParam('agentId') || 'default';
41
+ }
42
+ /**
43
+ * Initialise Jupyter configuration.
44
+ *
45
+ * Priority:
46
+ * 1. Query parameters (jupyterBaseUrl / jupyterToken)
47
+ * 2. <script id="jupyter-config-data"> block in the HTML page
48
+ */
49
+ function initJupyterConfig() {
50
+ // Load embedded config first
51
+ loadJupyterConfig();
52
+ // Override with query parameters when supplied by codeai
53
+ const qBaseUrl = getQueryParam('jupyterBaseUrl');
54
+ const qToken = getQueryParam('jupyterToken');
55
+ if (qBaseUrl)
56
+ setJupyterServerUrl(qBaseUrl);
57
+ if (qToken)
58
+ setJupyterServerToken(qToken);
59
+ // Also check for jupyter-config-data embedded in the page (may contain
60
+ // values injected at build/serve time)
61
+ const el = document.getElementById('jupyter-config-data');
62
+ if (el?.textContent) {
63
+ try {
64
+ const cfg = JSON.parse(el.textContent);
65
+ if (!qBaseUrl && cfg.baseUrl)
66
+ setJupyterServerUrl(cfg.baseUrl);
67
+ if (!qToken && cfg.token)
68
+ setJupyterServerToken(cfg.token);
69
+ }
70
+ catch {
71
+ // ignore
72
+ }
73
+ }
74
+ }
75
+ const NotebookPanel = ({ serviceManager }) => (_jsx(Box, { sx: {
76
+ flex: 1,
77
+ display: 'flex',
78
+ flexDirection: 'column',
79
+ overflow: 'hidden',
80
+ borderRight: '1px solid',
81
+ borderColor: 'border.default',
82
+ }, children: _jsx(JupyterReactTheme, { children: _jsx(Box, { sx: { height: '100vh' }, children: _jsx(Notebook, { nbformat: MatplotlibNotebook, id: NOTEBOOK_ID, serviceManager: serviceManager, height: "100vh", cellSidebarMargin: 120, startDefaultKernel: true }) }) }) }));
83
+ const ChatPanel = ({ agentId }) => {
84
+ // Register notebook tools so the agent can manipulate cells
85
+ const notebookTools = useNotebookTools(NOTEBOOK_ID);
86
+ return (_jsx(Box, { sx: {
87
+ width: '420px',
88
+ minWidth: '320px',
89
+ display: 'flex',
90
+ flexDirection: 'column',
91
+ overflow: 'hidden',
92
+ }, children: _jsx(Chat, { transport: "ag-ui", baseUrl: BASE_URL, agentId: agentId, title: "Agent Notebook", placeholder: "Ask about the notebook...", description: "Chat with the agent to manipulate the notebook", showHeader: true, height: "100vh", showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, showTokenUsage: true, showInformation: true, frontendTools: notebookTools, autoFocus: true, runtimeId: agentId, historyEndpoint: `${BASE_URL}/api/v1/history`, suggestions: [
93
+ {
94
+ title: 'Add a cell',
95
+ message: 'Insert a new code cell into the notebook',
96
+ },
97
+ {
98
+ title: 'Run first cell',
99
+ message: 'Run the first cell in the notebook',
100
+ },
101
+ {
102
+ title: 'Show cells',
103
+ message: 'Show the notebook cells content and compute the number of cells',
104
+ },
105
+ ], submitOnSuggestionClick: true }) }));
106
+ };
107
+ // ─── Main component ─────────────────────────────────────────────────────────
108
+ export const AgentNotebook = () => {
109
+ const [agentId] = useState(getAgentId);
110
+ const [isReady, setIsReady] = useState(false);
111
+ const [error, setError] = useState(null);
112
+ const [serviceManager, setServiceManager] = useState(null);
113
+ // Verify the agent exists AND initialise the Jupyter service manager
114
+ useEffect(() => {
115
+ let cancelled = false;
116
+ const init = async () => {
117
+ try {
118
+ // 1. Ensure agent exists — create if missing
119
+ const getResp = await fetch(`${BASE_URL}/api/v1/agents/${encodeURIComponent(agentId)}`);
120
+ if (!getResp.ok) {
121
+ const createResp = await fetch(`${BASE_URL}/api/v1/agents`, {
122
+ method: 'POST',
123
+ headers: { 'Content-Type': 'application/json' },
124
+ body: JSON.stringify({
125
+ name: agentId,
126
+ description: 'Agent created by Agent Notebook page',
127
+ agent_library: 'pydantic-ai',
128
+ transport: 'ag-ui',
129
+ model: DEFAULT_MODEL,
130
+ system_prompt: 'You are a helpful AI assistant that helps users work with Jupyter notebooks. You can help with code, explanations, and data analysis.',
131
+ }),
132
+ });
133
+ if (!createResp.ok && createResp.status !== 400) {
134
+ const d = await createResp.json().catch(() => ({}));
135
+ throw new Error(d.detail || `Failed to create agent: ${createResp.status}`);
136
+ }
137
+ }
138
+ // 2. Initialise Jupyter
139
+ initJupyterConfig();
140
+ const serverSettings = createServerSettings(getJupyterServerUrl(), getJupyterServerToken());
141
+ const manager = new ServiceManager({ serverSettings });
142
+ await manager.ready;
143
+ if (!cancelled) {
144
+ setServiceManager(manager);
145
+ setIsReady(true);
146
+ }
147
+ }
148
+ catch (err) {
149
+ if (!cancelled) {
150
+ setError(err instanceof Error ? err.message : 'Failed to initialise');
151
+ }
152
+ }
153
+ };
154
+ init();
155
+ return () => {
156
+ cancelled = true;
157
+ };
158
+ }, [agentId]);
159
+ // Loading
160
+ if (!isReady && !error) {
161
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
162
+ display: 'flex',
163
+ flexDirection: 'column',
164
+ alignItems: 'center',
165
+ justifyContent: 'center',
166
+ height: '100vh',
167
+ gap: 3,
168
+ bg: 'canvas.default',
169
+ }, children: [_jsx(Spinner, { size: "large" }), _jsxs(Text, { sx: { color: 'fg.muted' }, children: ["Connecting to agent ", agentId, "\u2026"] })] }) }));
170
+ }
171
+ // Error
172
+ if (error) {
173
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
174
+ display: 'flex',
175
+ flexDirection: 'column',
176
+ alignItems: 'center',
177
+ justifyContent: 'center',
178
+ height: '100vh',
179
+ gap: 3,
180
+ bg: 'canvas.default',
181
+ }, 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 })] }) }));
182
+ }
183
+ // Ready — notebook + chat side-by-side
184
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
185
+ display: 'flex',
186
+ height: '100vh',
187
+ width: '100vw',
188
+ overflow: 'hidden',
189
+ bg: 'canvas.default',
190
+ }, children: [serviceManager && _jsx(NotebookPanel, { serviceManager: serviceManager }), _jsx(ChatPanel, { agentId: agentId })] }) }));
191
+ };
192
+ export default AgentNotebook;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ import { createRoot } from 'react-dom/client';
7
+ import { AgentLexical } from './AgentLexical';
8
+ const rootElement = document.getElementById('root');
9
+ if (rootElement) {
10
+ createRoot(rootElement).render(_jsx(AgentLexical, {}));
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ import { createRoot } from 'react-dom/client';
7
+ import { Agent } from './Agent';
8
+ const rootElement = document.getElementById('root');
9
+ if (rootElement) {
10
+ createRoot(rootElement).render(_jsx(Agent, {}));
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ import { createRoot } from 'react-dom/client';
7
+ // import { Agent as AgentNotebook } from './Agent';
8
+ import { AgentNotebook } from './AgentNotebook';
9
+ const rootElement = document.getElementById('root');
10
+ if (rootElement) {
11
+ createRoot(rootElement).render(_jsx(AgentNotebook, {}));
12
+ }
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
- import type { Agent } from '../examples/stores/examplesStore';
3
- import type { Transport, Extension } from './chat';
2
+ import type { Agent } from '../types/Types';
3
+ import type { Transport } from './chat/components';
4
+ import type { Extension } from './chat/types';
4
5
  import type { McpServerSelection } from './McpServerManager';
5
6
  import type { OAuthProvider, Identity } from '../identity';
6
- import type { MCPServerTool as MCPServerToolType } from '../types';
7
+ import type { MCPServerTool as MCPServerToolType } from '../types/Types';
7
8
  /**
8
9
  * Agent spec entry from the library endpoint.
9
10
  */
@@ -43,25 +44,6 @@ export interface SkillOption {
43
44
  name: string;
44
45
  description?: string;
45
46
  }
46
- /**
47
- * MCP Server configuration from backend
48
- */
49
- export interface MCPServerConfig {
50
- id: string;
51
- name: string;
52
- url?: string;
53
- enabled: boolean;
54
- tools: MCPServerTool[];
55
- command?: string;
56
- args?: string[];
57
- isAvailable?: boolean;
58
- isRunning?: boolean;
59
- /** True if this server is from mcp.json config (vs catalog) */
60
- isConfig?: boolean;
61
- transport?: string;
62
- /** Required environment variables for this server */
63
- requiredEnvVars?: string[];
64
- }
65
47
  type AgentLibrary = 'pydantic-ai' | 'langchain' | 'jupyter-ai';
66
48
  export type { AgentLibrary };
67
49
  export type { Transport };
@@ -8,8 +8,8 @@ import { Text, TextInput, Button, FormControl, Select, Checkbox, Spinner, Flash,
8
8
  import { ToolsIcon, KeyIcon, SyncIcon, PlusIcon, XIcon, LinkExternalIcon, } from '@primer/octicons-react';
9
9
  import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
10
10
  import { Box } from '@datalayer/primer-addons';
11
+ import { IdentityCard } from './chat/components';
11
12
  import { IdentityConnect, useIdentity } from '../identity';
12
- import { IdentityCard } from './chat';
13
13
  /**
14
14
  * Helper: is the selected agent id a library spec?
15
15
  */
@@ -262,7 +262,7 @@ export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl,
262
262
  const isNewAgentMode = selectedAgentId === 'new-agent' || isSpecSelection(selectedAgentId);
263
263
  // True when a library spec is selected (fields locked down except Name, URL, Library, Model, Transport, Extensions)
264
264
  const isSpecMode = isSpecSelection(selectedAgentId);
265
- // Fetch skills from the backend (only when codemode is enabled)
265
+ // Fetch skills from the backend (always available, independent of codemode)
266
266
  const skillsQuery = useQuery({
267
267
  queryKey: ['agent-skills', baseUrl],
268
268
  queryFn: async () => {
@@ -272,7 +272,7 @@ export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl,
272
272
  }
273
273
  return response.json();
274
274
  },
275
- enabled: !!baseUrl && enableCodemode,
275
+ enabled: !!baseUrl,
276
276
  staleTime: 1000 * 60 * 5, // 5 minutes
277
277
  retry: 1,
278
278
  });
@@ -314,9 +314,9 @@ export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl,
314
314
  const configServers = mcpServersQuery.data || configQuery.data?.mcpServers || [];
315
315
  const catalogServers = catalogServersQuery.data || [];
316
316
  const models = configQuery.data?.models || [];
317
- // Use fetched skills when codemode is enabled, otherwise use passed availableSkills (which may be empty)
317
+ // Use fetched skills when available, otherwise use passed availableSkills (which may be empty)
318
318
  const fetchedSkills = skillsQuery.data?.skills || [];
319
- const displaySkills = enableCodemode ? fetchedSkills : availableSkills;
319
+ const displaySkills = fetchedSkills.length > 0 ? fetchedSkills : availableSkills;
320
320
  const skillsEnabled = selectedSkills.length > 0;
321
321
  const selectedConfigServers = selectedMcpServers
322
322
  .filter(s => s.origin === 'config')
@@ -452,14 +452,14 @@ export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl,
452
452
  color: 'fg.muted',
453
453
  fontWeight: 'normal',
454
454
  ml: 2,
455
- }, children: "\u2014 defined by spec" }))] }), _jsx(Box, { sx: { display: 'flex', gap: 4, opacity: isSpecMode ? 0.6 : 1 }, children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableCodemode, disabled: !isNewAgentMode || isSpecMode, onChange: e => onEnableCodemodeChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Codemode" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code to compose tools" })] })] }) }), skillsEnabled && enableCodemode && (_jsx(Flash, { variant: "default", sx: { mt: 3 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Skills provide curated capabilities; Codemode composes tools with Python for multi-step execution." }) })), enableCodemode && (_jsxs(Box, { sx: { mt: 3, display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: allowDirectToolCalls, disabled: !isNewAgentMode || isSpecMode, onChange: e => onAllowDirectToolCallsChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Allow direct tool calls" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Expose call_tool for simple, single-tool operations" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableToolReranker, disabled: !isNewAgentMode || isSpecMode, onChange: e => onEnableToolRerankerChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Enable tool reranker" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Reorder search results using the configured reranker" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: useJupyterSandbox, disabled: !isNewAgentMode || isSpecMode, onChange: e => onUseJupyterSandboxChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Use Jupyter Sandbox" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code in a Jupyter kernel instead of local-eval" })] })] })] }))] }), _jsxs(Box, { sx: {
455
+ }, children: "\u2014 defined by spec" }))] }), _jsx(Box, { sx: { display: 'flex', gap: 4, opacity: isSpecMode ? 0.6 : 1 }, children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableCodemode, disabled: !isNewAgentMode || isSpecMode, onChange: e => onEnableCodemodeChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Codemode" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code to compose tools" })] })] }) }), skillsEnabled && enableCodemode && (_jsx(Flash, { variant: "default", sx: { mt: 3 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Skills provide curated capabilities; Codemode composes tools with Python for multi-step execution." }) })), skillsEnabled && !enableCodemode && (_jsx(Flash, { variant: "default", sx: { mt: 3 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Skills will run with a standalone code sandbox for script execution. Enable Codemode to compose skills with other tools." }) })), enableCodemode && (_jsxs(Box, { sx: { mt: 3, display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: allowDirectToolCalls, disabled: !isNewAgentMode || isSpecMode, onChange: e => onAllowDirectToolCallsChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Allow direct tool calls" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Expose call_tool for simple, single-tool operations" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: enableToolReranker, disabled: !isNewAgentMode || isSpecMode, onChange: e => onEnableToolRerankerChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Enable tool reranker" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Reorder search results using the configured reranker" })] })] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Checkbox, { checked: useJupyterSandbox, disabled: !isNewAgentMode || isSpecMode, onChange: e => onUseJupyterSandboxChange?.(e.target.checked) }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontSize: 1 }, children: "Use Jupyter Sandbox" }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: "Execute code in a Jupyter kernel instead of local-eval" })] })] })] }))] }), _jsxs(Box, { sx: {
456
456
  marginBottom: 3,
457
457
  padding: 3,
458
458
  border: '1px solid',
459
459
  borderColor: 'border.default',
460
460
  borderRadius: 2,
461
461
  backgroundColor: 'canvas.default',
462
- opacity: isSpecMode ? 0.6 : enableCodemode ? 1 : 0.5,
462
+ opacity: isSpecMode ? 0.6 : 1,
463
463
  }, children: [_jsxs(Box, { sx: {
464
464
  display: 'flex',
465
465
  alignItems: 'center',
@@ -470,7 +470,7 @@ export const AgentConfiguration = ({ agentLibrary, transport, extensions, wsUrl,
470
470
  color: 'fg.muted',
471
471
  fontWeight: 'normal',
472
472
  ml: 2,
473
- }, children: "\u2014 defined by spec" }))] }), skillsQuery.isLoading && _jsx(Spinner, { size: "small" }), enableCodemode && !skillsQuery.isLoading && (_jsx(Button, { variant: "invisible", size: "small", onClick: () => skillsQuery.refetch(), sx: { padding: 1 }, "aria-label": "Refresh skills", children: _jsx(SyncIcon, { size: 14 }) }))] }), !enableCodemode ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Enable Codemode to use skills." })) : skillsQuery.isError ? (_jsx(Flash, { variant: "warning", sx: { marginBottom: 2 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Unable to fetch skills. Check that the server is running." }) })) : displaySkills.length === 0 && !skillsQuery.isLoading ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "No skills available." })) : (_jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: displaySkills.map(skill => (_jsxs(Box, { sx: {
473
+ }, children: "\u2014 defined by spec" }))] }), skillsQuery.isLoading && _jsx(Spinner, { size: "small" }), !skillsQuery.isLoading && (_jsx(Button, { variant: "invisible", size: "small", onClick: () => skillsQuery.refetch(), sx: { padding: 1 }, "aria-label": "Refresh skills", children: _jsx(SyncIcon, { size: 14 }) }))] }), skillsQuery.isError ? (_jsx(Flash, { variant: "warning", sx: { marginBottom: 2 }, children: _jsx(Text, { sx: { fontSize: 0 }, children: "Unable to fetch skills. Check that the server is running." }) })) : displaySkills.length === 0 && !skillsQuery.isLoading ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "No skills available." })) : (_jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: displaySkills.map(skill => (_jsxs(Box, { sx: {
474
474
  display: 'flex',
475
475
  alignItems: 'center',
476
476
  gap: 2,
@@ -26,9 +26,11 @@ export interface AgentDetailsProps {
26
26
  onIdentityDisconnect?: (provider: OAuthProvider) => void;
27
27
  /** Callback to go back to chat view */
28
28
  onBack: () => void;
29
+ /** Whether to show the header with back button (default: true) */
30
+ showBackHeader?: boolean;
29
31
  }
30
32
  /**
31
33
  * AgentDetails component displays comprehensive information about the agent.
32
34
  */
33
- export declare function AgentDetails({ name, protocol, url, messageCount, agentId, apiBase, identityProviders, onIdentityConnect, onIdentityDisconnect, onBack, }: AgentDetailsProps): import("react/jsx-runtime").JSX.Element;
35
+ export declare function AgentDetails({ name, protocol, url, messageCount, agentId, apiBase, identityProviders, onIdentityConnect, onIdentityDisconnect, onBack, showBackHeader, }: AgentDetailsProps): import("react/jsx-runtime").JSX.Element;
34
36
  export default AgentDetails;
@@ -5,7 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
5
5
  * AgentDetails component - Shows detailed information about the agent
6
6
  * including name, protocol, URL, message count, and context details.
7
7
  */
8
- import { ArrowLeftIcon, CheckCircleIcon, XCircleIcon, CodeIcon, ZapIcon, DownloadIcon, NoteIcon, ServerIcon, } from '@primer/octicons-react';
8
+ import { ArrowLeftIcon, CheckCircleIcon, XCircleIcon, CodeIcon, BriefcaseIcon, DownloadIcon, NoteIcon, ServerIcon, } from '@primer/octicons-react';
9
9
  import { Button, Heading, IconButton, Text, Label, Spinner, ToggleSwitch, } from '@primer/react';
10
10
  import { Box } from '@datalayer/primer-addons';
11
11
  import { AiAgentIcon } from '@datalayer/icons-react';
@@ -171,7 +171,7 @@ async function downloadContextSnapshotAsCSV(agentId, apiBase) {
171
171
  /**
172
172
  * AgentDetails component displays comprehensive information about the agent.
173
173
  */
174
- export function AgentDetails({ name = 'AI Agent', protocol, url, messageCount, agentId, apiBase, identityProviders, onIdentityConnect, onIdentityDisconnect, onBack, }) {
174
+ export function AgentDetails({ name = 'AI Agent', protocol, url, messageCount, agentId, apiBase, identityProviders, onIdentityConnect, onIdentityDisconnect, onBack, showBackHeader = true, }) {
175
175
  const queryClient = useQueryClient();
176
176
  // Fetch MCP toolsets status
177
177
  const { data: mcpStatus, isLoading: mcpLoading } = useQuery({
@@ -239,14 +239,14 @@ export function AgentDetails({ name = 'AI Agent', protocol, url, messageCount, a
239
239
  height: '100%',
240
240
  bg: 'canvas.default',
241
241
  overflow: 'auto',
242
- }, children: [_jsxs(Box, { sx: {
242
+ }, children: [showBackHeader && (_jsxs(Box, { sx: {
243
243
  display: 'flex',
244
244
  alignItems: 'center',
245
245
  gap: 2,
246
246
  p: 3,
247
247
  borderBottom: '1px solid',
248
248
  borderColor: 'border.default',
249
- }, children: [_jsx(IconButton, { icon: ArrowLeftIcon, "aria-label": "Back to chat", variant: "invisible", onClick: onBack }), _jsx(Heading, { as: "h2", sx: { fontSize: 3, fontWeight: 'semibold' }, children: "Agent Details" })] }), _jsxs(Box, { sx: { p: 3, display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsxs(Box, { sx: {
249
+ }, children: [_jsx(IconButton, { icon: ArrowLeftIcon, "aria-label": "Back to chat", variant: "invisible", onClick: onBack }), _jsx(Heading, { as: "h2", sx: { fontSize: 3, fontWeight: 'semibold' }, children: "Agent Details" })] })), _jsxs(Box, { sx: { p: 3, display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsxs(Box, { sx: {
250
250
  display: 'flex',
251
251
  alignItems: 'center',
252
252
  gap: 3,
@@ -557,7 +557,7 @@ export function AgentDetails({ name = 'AI Agent', protocol, url, messageCount, a
557
557
  overflow: 'hidden',
558
558
  textOverflow: 'ellipsis',
559
559
  whiteSpace: 'nowrap',
560
- }, title: codemodeStatus.sandbox.python_path, children: codemodeStatus.sandbox.python_path })] }))] })] })), codemodeStatus.skills.length > 0 && (_jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 1 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(ZapIcon, { size: 16 }), _jsxs(Text, { sx: {
560
+ }, title: codemodeStatus.sandbox.python_path, children: codemodeStatus.sandbox.python_path })] }))] })] })), codemodeStatus.skills.length > 0 && (_jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 1 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(BriefcaseIcon, { size: 16 }), _jsxs(Text, { sx: {
561
561
  fontSize: 0,
562
562
  fontWeight: 'semibold',
563
563
  color: 'fg.muted',
@@ -594,6 +594,6 @@ export function AgentDetails({ name = 'AI Agent', protocol, url, messageCount, a
594
594
  borderRadius: 2,
595
595
  border: '1px solid',
596
596
  borderColor: 'border.default',
597
- }, children: _jsx(ContextInspector, { agentId: agentId, apiBase: apiBase }) })] })), _jsx(AgentIdentity, { providers: identityProviders, title: "Connected Accounts", showHeader: true, showDescription: true, description: "OAuth identities connected to this agent. Agents can use these to access external services like GitHub repositories on your behalf.", showExpirationDetails: true, allowReconnect: Boolean(identityProviders), onConnect: onIdentityConnect, onDisconnect: onIdentityDisconnect }), _jsx(Box, { sx: { mt: 2 }, children: _jsx(Button, { variant: "primary", onClick: onBack, sx: { width: '100%' }, children: "Back to Chat" }) })] })] }));
597
+ }, children: _jsx(ContextInspector, { agentId: agentId, apiBase: apiBase }) })] })), _jsx(AgentIdentity, { providers: identityProviders, title: "Connected Accounts", showHeader: true, showDescription: true, description: "OAuth identities connected to this agent. Agents can use these to access external services like GitHub repositories on your behalf.", showExpirationDetails: true, allowReconnect: Boolean(identityProviders), onConnect: onIdentityConnect, onDisconnect: onIdentityDisconnect }), showBackHeader && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(Button, { variant: "primary", onClick: onBack, sx: { width: '100%' }, children: "Back to Chat" }) }))] })] }));
598
598
  }
599
599
  export default AgentDetails;
@@ -1,5 +1,6 @@
1
1
  import { type Suggestion } from './base/ChatBase';
2
- import type { ModelConfig } from './base/ChatBase';
2
+ import type { ModelConfig, ChatViewMode } from './base/ChatBase';
3
+ import type { FrontendToolDefinition } from '../types/tool';
3
4
  import type { McpServerSelection } from '../types';
4
5
  import type { OAuthProvider, OAuthProviderConfig, Identity } from '../../../identity';
5
6
  /**
@@ -105,9 +106,14 @@ export interface ChatProps {
105
106
  * Endpoint URL for fetching conversation history.
106
107
  * When runtimeId is provided, this endpoint is called to fetch
107
108
  * the conversation history on mount.
108
- * If not provided, defaults to `{protocol.endpoint}/history`.
109
+ * If not provided, defaults to `{protocol.endpoint}/api/v1/history`.
109
110
  */
110
111
  historyEndpoint?: string;
112
+ /**
113
+ * A prompt to append and send after the conversation history is loaded.
114
+ * The message is shown in the chat and sent to the agent exactly once.
115
+ */
116
+ pendingPrompt?: string;
111
117
  /**
112
118
  * Error banner to display at the top of the chat.
113
119
  * Use this to show sandbox connection errors or other warnings.
@@ -116,6 +122,26 @@ export interface ChatProps {
116
122
  message: string;
117
123
  variant?: 'danger' | 'warning';
118
124
  };
125
+ /**
126
+ * Show the information icon in the header.
127
+ * When clicked, it opens the agent details panel.
128
+ * @default false
129
+ */
130
+ showInformation?: boolean;
131
+ /**
132
+ * Current chat view mode for the header segmented toggle.
133
+ * When provided, a view-mode toggle is rendered in the header.
134
+ */
135
+ chatViewMode?: ChatViewMode;
136
+ /**
137
+ * Callback when the user switches chat view mode via the header toggle.
138
+ */
139
+ onChatViewModeChange?: (mode: ChatViewMode) => void;
140
+ /**
141
+ * Frontend tool definitions to register with the chat.
142
+ * Pass an empty array to explicitly disable all frontend tools.
143
+ */
144
+ frontendTools?: FrontendToolDefinition[];
119
145
  }
120
146
  /**
121
147
  * Chat Component
@@ -158,5 +184,5 @@ export interface ChatProps {
158
184
  * />
159
185
  * ```
160
186
  */
161
- export declare function Chat({ transport, extensions: _extensions, baseUrl, wsUrl, agentId, placeholder, title, autoConnect: _autoConnect, streaming: _streaming, onMessageSent: _onMessageSent, onMessageReceived: _onMessageReceived, onDisconnect, onLogout: _onLogout, onCollapsePanel: _onCollapsePanel, className, height, showHeader, showModelSelector, showToolsMenu, showSkillsMenu, codemodeEnabled, showTokenUsage, initialModel, availableModels, mcpServers, initialSkills, clearOnMount: _clearOnMount, suggestions, submitOnSuggestionClick, description, autoFocus, identityProviders, onIdentityConnect, onIdentityDisconnect, runtimeId, historyEndpoint, errorBanner, }: ChatProps): import("react/jsx-runtime").JSX.Element;
187
+ export declare function Chat({ transport, extensions: _extensions, baseUrl, wsUrl, agentId, placeholder, title, autoConnect: _autoConnect, streaming: _streaming, onMessageSent: _onMessageSent, onMessageReceived: _onMessageReceived, onDisconnect, onLogout: _onLogout, onCollapsePanel: _onCollapsePanel, className, height, showHeader, showModelSelector, showToolsMenu, showSkillsMenu, codemodeEnabled, showTokenUsage, initialModel, availableModels, mcpServers, initialSkills, clearOnMount: _clearOnMount, suggestions, submitOnSuggestionClick, description, autoFocus, identityProviders, onIdentityConnect, onIdentityDisconnect, runtimeId, historyEndpoint, pendingPrompt, errorBanner, showInformation, chatViewMode, onChatViewModeChange, frontendTools, }: ChatProps): import("react/jsx-runtime").JSX.Element;
162
188
  export default Chat;