@datalayer/agent-runtimes 0.0.11 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) 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 +33 -0
  5. package/lib/AgentLexical.js +295 -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/AgentRuntimeLexical2Example.d.ts +0 -1
  55. package/lib/examples/AgentRuntimeLexical2Example.js +0 -1
  56. package/lib/examples/AgentRuntimeLexicalExample.d.ts +0 -1
  57. package/lib/examples/AgentRuntimeLexicalExample.js +6 -4
  58. package/lib/examples/AgentRuntimeLexicalSidebarExample.d.ts +0 -1
  59. package/lib/examples/AgentRuntimeLexicalSidebarExample.js +8 -2
  60. package/lib/examples/AgentRuntimeNotebookExample.js +6 -5
  61. package/lib/examples/CopilotKitLexicalExample.d.ts +0 -1
  62. package/lib/examples/CopilotKitLexicalExample.js +0 -1
  63. package/lib/examples/CopilotKitNotebookExample.js +2 -2
  64. package/lib/examples/JupyterNotebookExample.js +2 -2
  65. package/lib/{components → examples/components}/Header.d.ts +2 -1
  66. package/lib/{components → examples/components}/HeaderControls.js +1 -1
  67. package/lib/{components → examples/components}/LexicalEditor.d.ts +6 -1
  68. package/lib/{components → examples/components}/LexicalEditor.js +4 -4
  69. package/lib/{components → examples/components}/MainContent.d.ts +1 -1
  70. package/lib/{components → examples/components}/MainContent.js +7 -5
  71. package/lib/examples/components/index.d.ts +16 -0
  72. package/lib/examples/components/index.js +13 -0
  73. package/lib/examples/example-selector.js +2 -1
  74. package/lib/examples/index.d.ts +1 -1
  75. package/lib/examples/index.js +1 -1
  76. package/lib/examples/main.js +2 -2
  77. package/lib/examples/stores/examplesStore.d.ts +2 -23
  78. package/lib/index.d.ts +2 -1
  79. package/lib/index.js +1 -0
  80. package/lib/lexical/ChatInlinePlugin.d.ts +13 -2
  81. package/lib/lexical/ChatInlinePlugin.js +66 -183
  82. package/lib/lexical/index.d.ts +1 -0
  83. package/lib/lexical/index.js +1 -0
  84. package/lib/lexical/useChatInlineToolbarItems.d.ts +35 -0
  85. package/lib/lexical/useChatInlineToolbarItems.js +91 -0
  86. package/lib/runtime/useAgentRuntime.d.ts +1 -1
  87. package/lib/runtime/useAgentRuntime.js +1 -1
  88. package/lib/{config/agents/code-ai → specs/agents/codeai}/agents.d.ts +5 -2
  89. package/lib/specs/agents/codeai/agents.js +151 -0
  90. package/lib/{config → specs}/agents/codemode-paper/agents.d.ts +4 -2
  91. package/lib/{config → specs}/agents/codemode-paper/agents.js +39 -19
  92. package/lib/{config → specs}/agents/datalayer-ai/agents.d.ts +4 -2
  93. package/lib/{config → specs}/agents/datalayer-ai/agents.js +17 -2
  94. package/lib/{config → specs}/agents/index.d.ts +3 -1
  95. package/lib/{config → specs}/agents/index.js +12 -3
  96. package/lib/{config → specs}/envvars.d.ts +1 -0
  97. package/lib/{config → specs}/envvars.js +10 -0
  98. package/lib/specs/index.d.ts +5 -0
  99. package/lib/specs/index.js +9 -0
  100. package/lib/{config → specs}/mcpServers.d.ts +2 -1
  101. package/lib/{config → specs}/mcpServers.js +23 -1
  102. package/lib/specs/models.d.ts +68 -0
  103. package/lib/specs/models.js +239 -0
  104. package/lib/state/substates/AIAgentState.d.ts +0 -1
  105. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.d.ts +11 -22
  106. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.js +5 -5
  107. package/lib/tools/adapters/agent-runtimes/lexicalHooks.d.ts +6 -6
  108. package/lib/tools/adapters/agent-runtimes/lexicalHooks.js +4 -4
  109. package/lib/tools/adapters/agent-runtimes/notebookHooks.d.ts +6 -6
  110. package/lib/tools/adapters/agent-runtimes/notebookHooks.js +4 -4
  111. package/lib/{types.d.ts → types/Types.d.ts} +32 -6
  112. package/lib/types/index.d.ts +1 -0
  113. package/lib/types/index.js +1 -0
  114. package/package.json +11 -5
  115. package/scripts/codegen/generate_agents.py +53 -13
  116. package/scripts/codegen/generate_envvars.py +1 -1
  117. package/scripts/codegen/generate_mcp_servers.py +5 -5
  118. package/scripts/codegen/generate_models.py +486 -0
  119. package/scripts/codegen/generate_skills.py +2 -2
  120. package/style/primer-primitives.css +22 -0
  121. package/lib/components/chat/components/elements/ChatInputPrompt.d.ts +0 -37
  122. package/lib/components/chat/components/elements/ChatInputPrompt.js +0 -150
  123. package/lib/config/agents/code-ai/agents.js +0 -70
  124. /package/lib/{components → examples/components}/FooterMetrics.d.ts +0 -0
  125. /package/lib/{components → examples/components}/FooterMetrics.js +0 -0
  126. /package/lib/{components → examples/components}/Header.js +0 -0
  127. /package/lib/{components → examples/components}/HeaderControls.d.ts +0 -0
  128. /package/lib/{components → examples/components}/MockFileBrowser.d.ts +0 -0
  129. /package/lib/{components → examples/components}/MockFileBrowser.js +0 -0
  130. /package/lib/{components → examples/components}/SessionTabs.d.ts +0 -0
  131. /package/lib/{components → examples/components}/SessionTabs.js +0 -0
  132. /package/lib/{components → examples/components}/TimeTravel.d.ts +0 -0
  133. /package/lib/{components → examples/components}/TimeTravel.js +0 -0
  134. /package/lib/{config/agents/code-ai → specs/agents/codeai}/index.d.ts +0 -0
  135. /package/lib/{config/agents/code-ai → specs/agents/codeai}/index.js +0 -0
  136. /package/lib/{config → specs}/agents/codemode-paper/index.d.ts +0 -0
  137. /package/lib/{config → specs}/agents/codemode-paper/index.js +0 -0
  138. /package/lib/{config → specs}/agents/datalayer-ai/index.d.ts +0 -0
  139. /package/lib/{config → specs}/agents/datalayer-ai/index.js +0 -0
  140. /package/lib/{config → specs}/skills.d.ts +0 -0
  141. /package/lib/{config → specs}/skills.js +0 -0
  142. /package/lib/{types.js → types/Types.js} +0 -0
@@ -56,6 +56,6 @@ export { BaseProtocolAdapter, AGUIAdapter, A2AAdapter, ACPAdapter, type AGUIAdap
56
56
  export { ToolExecutor, type ToolExecutionContext } from './tools';
57
57
  export { MiddlewarePipeline, createMiddleware, loggingMiddleware, createHITLMiddleware, type RequestContext, type ResponseContext, } from './middleware';
58
58
  export { ExtensionRegistry, createMessageRenderer, createActivityRenderer, createA2UIRenderer, A2UIExtensionImpl, type A2UIMessage, type InternalExtensionType, } from './extensions';
59
- export { ChatMessages, ChatInputPrompt, ChatSidebar, ChatStandalone, ChatBase, ToolApprovalDialog, useToolApprovalDialog, PoweredByTag, FloatingBrandButton, ChatHeader, MessagePart, TextPart, ReasoningPart, ToolPart, DynamicToolPart, ToolCallDisplay, Chat, ChatFloating, AgentDetails, AgentIdentity, IdentityCard, getTokenStatus, formatDuration, formatExpirationStatus, type ChatMessagesProps, type ChatInputPromptProps, type ChatSidebarProps, type ChatStandaloneProps, type MessageHandler, type ChatBaseProps, type ProtocolConfig, type AgentRuntimeConfig, type AvatarConfig, type EmptyStateConfig, type HeaderButtonsConfig, type StreamingMessageOptions, type ToolApprovalDialogProps, type PoweredByTagProps, type FloatingBrandButtonProps, type ChatFloatingProps, type ToolCallRenderContext, type ToolCallStatus, type RenderToolResult, type RespondCallback, type Suggestion, type RemoteConfig, type ModelConfig, type BuiltinTool, type MCPServerConfig, type MCPServerTool, type AgentDetailsProps, type AgentIdentityProps, type IdentityCardProps, type TokenStatus, type ChatHeaderProps, type ConnectionState, type MessagePartProps, type TextPartProps, type ReasoningPartProps, type ToolPartProps, type DynamicToolPartProps, type ToolCallDisplayProps, type ChatProps, type Transport, type Extension, } from './components';
59
+ export { ChatMessages, ChatSidebar, ChatStandalone, ChatBase, InputPrompt, ToolApprovalDialog, useToolApprovalDialog, PoweredByTag, FloatingBrandButton, ChatHeader, MessagePart, TextPart, ReasoningPart, ToolPart, DynamicToolPart, ToolCallDisplay, Chat, ChatFloating, AgentDetails, AgentIdentity, IdentityCard, getTokenStatus, formatDuration, formatExpirationStatus, type ChatMessagesProps, type ChatSidebarProps, type ChatStandaloneProps, type MessageHandler, type ChatBaseProps, type ProtocolConfig, type AgentRuntimeConfig, type AvatarConfig, type EmptyStateConfig, type HeaderButtonsConfig, type StreamingMessageOptions, type ChatViewMode, type InputPromptProps, type ToolApprovalDialogProps, type PoweredByTagProps, type FloatingBrandButtonProps, type ChatFloatingProps, type ToolCallRenderContext, type ToolCallStatus, type RenderToolResult, type RespondCallback, type Suggestion, type RemoteConfig, type ModelConfig, type BuiltinTool, type MCPServerConfig, type MCPServerTool, type AgentDetailsProps, type AgentIdentityProps, type IdentityCardProps, type TokenStatus, type ChatHeaderProps, type ConnectionState, type MessagePartProps, type TextPartProps, type ReasoningPartProps, type ToolPartProps, type DynamicToolPartProps, type ToolCallDisplayProps, type ChatProps, type Transport, type Extension, } from './components';
60
60
  export { requestAPI } from './handler';
61
61
  export { useKeyboardShortcuts, useChatKeyboardShortcuts, getShortcutDisplay, type KeyboardShortcut, type UseKeyboardShortcutsOptions, } from '../../hooks';
@@ -69,7 +69,7 @@ export { MiddlewarePipeline, createMiddleware, loggingMiddleware, createHITLMidd
69
69
  // Extensions
70
70
  export { ExtensionRegistry, createMessageRenderer, createActivityRenderer, createA2UIRenderer, A2UIExtensionImpl, } from './extensions';
71
71
  // Components
72
- export { ChatMessages, ChatInputPrompt, ChatSidebar, ChatStandalone, ChatBase, ToolApprovalDialog, useToolApprovalDialog, PoweredByTag, FloatingBrandButton, ChatHeader, MessagePart, TextPart, ReasoningPart, ToolPart, DynamicToolPart, ToolCallDisplay, Chat, ChatFloating, AgentDetails, AgentIdentity, IdentityCard, getTokenStatus, formatDuration, formatExpirationStatus, } from './components';
72
+ export { ChatMessages, ChatSidebar, ChatStandalone, ChatBase, InputPrompt, ToolApprovalDialog, useToolApprovalDialog, PoweredByTag, FloatingBrandButton, ChatHeader, MessagePart, TextPart, ReasoningPart, ToolPart, DynamicToolPart, ToolCallDisplay, Chat, ChatFloating, AgentDetails, AgentIdentity, IdentityCard, getTokenStatus, formatDuration, formatExpirationStatus, } from './components';
73
73
  // Simple API request handler (merged from chat)
74
74
  export { requestAPI } from './handler';
75
75
  // Keyboard shortcuts (re-exported from main hooks folder)
@@ -260,18 +260,22 @@ export class DatalayerInferenceProvider extends BaseInferenceProvider {
260
260
  function: {
261
261
  name: tool.name,
262
262
  description: tool.description,
263
- parameters: {
264
- type: 'object',
265
- properties: Object.fromEntries(tool.parameters.map(p => [
266
- p.name,
267
- {
268
- type: p.type || 'string',
269
- description: p.description,
270
- enum: p.enum,
271
- },
272
- ])),
273
- required: tool.parameters.filter(p => p.required).map(p => p.name),
274
- },
263
+ parameters: Array.isArray(tool.parameters)
264
+ ? {
265
+ type: 'object',
266
+ properties: Object.fromEntries(tool.parameters.map(p => [
267
+ p.name,
268
+ {
269
+ type: p.type || 'string',
270
+ description: p.description,
271
+ enum: p.enum,
272
+ },
273
+ ])),
274
+ required: tool.parameters
275
+ .filter(p => p.required)
276
+ .map(p => p.name),
277
+ }
278
+ : tool.parameters,
275
279
  },
276
280
  }));
277
281
  }
@@ -201,18 +201,22 @@ export class SelfHostedInferenceProvider extends BaseInferenceProvider {
201
201
  function: {
202
202
  name: tool.name,
203
203
  description: tool.description,
204
- parameters: {
205
- type: 'object',
206
- properties: Object.fromEntries(tool.parameters.map(p => [
207
- p.name,
208
- {
209
- type: p.type || 'string',
210
- description: p.description,
211
- enum: p.enum,
212
- },
213
- ])),
214
- required: tool.parameters.filter(p => p.required).map(p => p.name),
215
- },
204
+ parameters: Array.isArray(tool.parameters)
205
+ ? {
206
+ type: 'object',
207
+ properties: Object.fromEntries(tool.parameters.map(p => [
208
+ p.name,
209
+ {
210
+ type: p.type || 'string',
211
+ description: p.description,
212
+ enum: p.enum,
213
+ },
214
+ ])),
215
+ required: tool.parameters
216
+ .filter(p => p.required)
217
+ .map(p => p.name),
218
+ }
219
+ : tool.parameters,
216
220
  },
217
221
  }));
218
222
  }
@@ -25,9 +25,12 @@ export declare class AGUIAdapter extends BaseProtocolAdapter {
25
25
  private abortController;
26
26
  private currentThreadId;
27
27
  private pendingToolCalls;
28
+ private collectedToolResults;
28
29
  private messageHistory;
29
30
  private lastAssistantContent;
31
+ private lastTurnContent;
30
32
  private lastTools;
33
+ private isContinuation;
31
34
  constructor(config: AGUIAdapterConfig);
32
35
  /**
33
36
  * Connect to AG-UI endpoint (SSE doesn't require persistent connection)
@@ -65,10 +68,14 @@ export declare class AGUIAdapter extends BaseProtocolAdapter {
65
68
  }>;
66
69
  }): Promise<void>;
67
70
  /**
68
- * Send tool result back through AG-UI and continue the conversation
71
+ * Send tool result back through AG-UI and continue the conversation.
69
72
  *
70
- * AG-UI requires tool results to be sent as a new request with the full
71
- * message history including the tool result as a message with role: "tool"
73
+ * When the agent makes multiple tool calls in a single run, each call
74
+ * triggers an independent async execution in ChatBase. This method
75
+ * **batches** the results: it stores each result as it arrives and only
76
+ * sends ONE continuation request once ALL pending tool calls have been
77
+ * resolved. This prevents duplicate/concurrent SSE streams, corrupted
78
+ * shared state, and duplicate agent responses.
72
79
  */
73
80
  sendToolResult(toolCallId: string, result: ToolExecutionResult): Promise<void>;
74
81
  /**
@@ -16,10 +16,24 @@ export class AGUIAdapter extends BaseProtocolAdapter {
16
16
  currentThreadId = null;
17
17
  // Track in-progress tool calls to accumulate args and emit results
18
18
  pendingToolCalls = new Map();
19
+ // Collect tool results for batching — when the agent makes multiple tool
20
+ // calls in a single run, we must wait for ALL results before sending one
21
+ // combined continuation request. Without this, each sendToolResult would
22
+ // fire its own sendMessage → SSE stream, causing duplicate/concurrent
23
+ // continuation runs, corrupted shared state, and duplicate agent responses.
24
+ collectedToolResults = new Map();
19
25
  // Store conversation history for tool result continuation
20
26
  messageHistory = [];
21
27
  lastAssistantContent = '';
28
+ // Text from the current turn only (not accumulated across continuations).
29
+ // Used for the message history sent to the LLM so each assistant message
30
+ // contains only its own text, preventing the LLM from seeing duplicated
31
+ // context that confuses it into making extra tool calls.
32
+ lastTurnContent = '';
22
33
  lastTools = [];
34
+ // Continuation tracking — each continuation creates a new message bubble
35
+ // that appears after the tool calls in the chat display.
36
+ isContinuation = false;
23
37
  constructor(config) {
24
38
  super(config);
25
39
  // Ensure baseUrl ends with trailing slash (required for mounted Starlette apps)
@@ -98,7 +112,13 @@ export class AGUIAdapter extends BaseProtocolAdapter {
98
112
  // Store message history and tools for potential tool result continuation
99
113
  this.messageHistory = [...allMessages];
100
114
  this.lastTools = options?.tools || [];
101
- this.lastAssistantContent = '';
115
+ // Only clear assistant content for fresh user messages, not continuations.
116
+ // For continuations, lastTurnContent is used in sendToolResult to build
117
+ // the assistant message content in the LLM history.
118
+ if (!this.isContinuation) {
119
+ this.lastAssistantContent = '';
120
+ this.lastTurnContent = '';
121
+ }
102
122
  // Convert ChatMessages to AG-UI message format
103
123
  // AG-UI expects:
104
124
  // - Assistant messages with tool_calls array for tool invocations
@@ -184,26 +204,28 @@ export class AGUIAdapter extends BaseProtocolAdapter {
184
204
  }
185
205
  }
186
206
  /**
187
- * Send tool result back through AG-UI and continue the conversation
207
+ * Send tool result back through AG-UI and continue the conversation.
188
208
  *
189
- * AG-UI requires tool results to be sent as a new request with the full
190
- * message history including the tool result as a message with role: "tool"
209
+ * When the agent makes multiple tool calls in a single run, each call
210
+ * triggers an independent async execution in ChatBase. This method
211
+ * **batches** the results: it stores each result as it arrives and only
212
+ * sends ONE continuation request once ALL pending tool calls have been
213
+ * resolved. This prevents duplicate/concurrent SSE streams, corrupted
214
+ * shared state, and duplicate agent responses.
191
215
  */
192
216
  async sendToolResult(toolCallId, result) {
193
- // First emit local event for UI updates
217
+ // 1. Emit local event for UI updates
194
218
  this.emit({
195
219
  type: 'tool-result',
196
220
  toolResult: result,
197
221
  timestamp: new Date(),
198
222
  });
199
- // Get the tool name and args from pending tool calls
223
+ // 2. Retrieve tool metadata from pending map
200
224
  const pendingToolCall = this.pendingToolCalls.get(toolCallId);
201
225
  if (!pendingToolCall) {
202
226
  console.warn('[AGUIAdapter] No pending tool call found for ID:', toolCallId);
203
- console.log('[AGUIAdapter] Pending tool calls:', Array.from(this.pendingToolCalls.keys()));
204
227
  }
205
228
  const toolName = pendingToolCall?.toolName || 'unknown';
206
- // Parse the args safely
207
229
  let parsedArgs = {};
208
230
  if (pendingToolCall?.argsJson) {
209
231
  try {
@@ -213,54 +235,87 @@ export class AGUIAdapter extends BaseProtocolAdapter {
213
235
  console.warn('[AGUIAdapter] Failed to parse tool args:', e);
214
236
  }
215
237
  }
216
- // Build the assistant message that contained the tool call
217
- // AG-UI expects assistant messages with tool_calls to potentially have empty content
218
- const assistantMessageWithToolCall = {
238
+ // 3. Collect this result (batching)
239
+ this.collectedToolResults.set(toolCallId, {
240
+ toolCallId,
241
+ toolName,
242
+ parsedArgs,
243
+ result,
244
+ });
245
+ // 4. Check whether ALL pending tool calls now have results
246
+ const allResolved = Array.from(this.pendingToolCalls.keys()).every(id => this.collectedToolResults.has(id));
247
+ if (!allResolved) {
248
+ // Other tool calls are still executing — wait for them
249
+ return;
250
+ }
251
+ // ── All tool results collected — build ONE combined continuation ──
252
+ // 5. Build a single assistant message containing ALL tool calls
253
+ const toolCalls = Array.from(this.collectedToolResults.values()).map(tr => ({
254
+ type: 'tool-call',
255
+ toolCallId: tr.toolCallId,
256
+ toolName: tr.toolName,
257
+ args: tr.parsedArgs,
258
+ status: 'completed',
259
+ }));
260
+ const assistantMessageWithToolCalls = {
219
261
  id: generateMessageId(),
220
262
  role: 'assistant',
221
- content: this.lastAssistantContent || '',
263
+ // Use turn-only content for the history so the LLM doesn't see
264
+ // accumulated text from previous turns (which causes duplicate context
265
+ // and spurious extra tool calls).
266
+ content: this.lastTurnContent || this.lastAssistantContent || '',
222
267
  createdAt: new Date(),
223
- toolCalls: [
224
- {
225
- type: 'tool-call',
226
- toolCallId,
227
- toolName,
228
- args: parsedArgs,
229
- status: 'completed',
230
- },
231
- ],
268
+ toolCalls,
232
269
  };
233
- // Build the tool result message
234
- const toolResultMessage = {
270
+ // 6. Build individual tool-result messages (one per tool call)
271
+ const toolResultMessages = Array.from(this.collectedToolResults.values()).map(tr => ({
235
272
  id: generateMessageId(),
236
273
  role: 'tool',
237
- content: typeof result.result === 'string'
238
- ? result.result
239
- : JSON.stringify(result.result),
274
+ content: typeof tr.result.result === 'string'
275
+ ? tr.result.result
276
+ : JSON.stringify(tr.result.result),
240
277
  createdAt: new Date(),
241
278
  metadata: {
242
- toolCallId,
243
- toolName,
244
- isError: !result.success,
279
+ toolCallId: tr.toolCallId,
280
+ toolName: tr.toolName,
281
+ isError: !tr.result.success,
245
282
  },
246
- };
247
- // Build full message history for continuation
283
+ }));
284
+ // 7. Assemble full continuation history
248
285
  const continuationMessages = [
249
286
  ...this.messageHistory,
250
- assistantMessageWithToolCall,
251
- toolResultMessage,
287
+ assistantMessageWithToolCalls,
288
+ ...toolResultMessages,
252
289
  ];
253
- // Update stored message history
290
+ // 8. Clear batching state BEFORE the async sendMessage call
291
+ // (pendingToolCalls will be repopulated by the next stream if needed)
292
+ this.pendingToolCalls.clear();
293
+ this.collectedToolResults.clear();
294
+ // 9. Update stored message history
254
295
  this.messageHistory = continuationMessages;
255
- // Send continuation request to get agent's response to the tool result
256
- // This will trigger a new SSE stream with the agent's response
257
- await this.sendMessage(toolResultMessage, {
296
+ // DEBUG: Log continuation messages to inspect what the LLM sees
297
+ console.log('[AGUIAdapter] === CONTINUATION MESSAGES ===');
298
+ continuationMessages.forEach((msg, i) => {
299
+ const toolCallInfo = msg.toolCalls
300
+ ? ` [${msg.toolCalls.length} tool_calls: ${msg.toolCalls.map(tc => tc.toolName).join(', ')}]`
301
+ : '';
302
+ const metaInfo = msg.metadata?.toolCallId
303
+ ? ` [tool_call_id=${msg.metadata.toolCallId}]`
304
+ : '';
305
+ const contentPreview = typeof msg.content === 'string' ? msg.content.slice(0, 80) : '';
306
+ console.log(`[AGUIAdapter] [${i}] role=${msg.role}${toolCallInfo}${metaInfo} content="${contentPreview}"`);
307
+ });
308
+ console.log('[AGUIAdapter] === END CONTINUATION MESSAGES ===');
309
+ // 10. Mark as continuation (for internal tracking; the continuation
310
+ // will create a new message bubble that appears after the tool calls).
311
+ this.isContinuation = true;
312
+ // 11. Send ONE continuation request with all tool results
313
+ const lastToolResultMsg = toolResultMessages[toolResultMessages.length - 1];
314
+ await this.sendMessage(lastToolResultMsg, {
258
315
  messages: continuationMessages,
259
316
  tools: this.lastTools,
260
317
  threadId: this.currentThreadId || undefined,
261
318
  });
262
- // Clear the pending tool call
263
- this.pendingToolCalls.delete(toolCallId);
264
319
  }
265
320
  /**
266
321
  * Check feature support
@@ -285,8 +340,17 @@ export class AGUIAdapter extends BaseProtocolAdapter {
285
340
  }
286
341
  const decoder = new TextDecoder();
287
342
  let buffer = '';
343
+ // Always start fresh — each turn gets its own message bubble.
344
+ // Continuations will naturally appear AFTER the tool calls in the
345
+ // display because they create a new message that is appended at the
346
+ // end of displayItems.
288
347
  let currentMessageId = null;
289
348
  let currentContent = '';
349
+ // Track just the current turn's text (not accumulated) for the message
350
+ // history sent to the LLM on the next continuation.
351
+ let currentTurnContent = '';
352
+ // Consume the flag — it was set by sendToolResult for this call only
353
+ this.isContinuation = false;
290
354
  try {
291
355
  while (true) {
292
356
  const { done, value } = await reader.read();
@@ -317,6 +381,10 @@ export class AGUIAdapter extends BaseProtocolAdapter {
317
381
  resetContent: () => {
318
382
  currentContent = '';
319
383
  },
384
+ appendTurnContent: content => {
385
+ currentTurnContent += content;
386
+ },
387
+ getCurrentTurnContent: () => currentTurnContent,
320
388
  });
321
389
  }
322
390
  catch (e) {
@@ -345,13 +413,21 @@ export class AGUIAdapter extends BaseProtocolAdapter {
345
413
  const eventType = event.type;
346
414
  switch (eventType) {
347
415
  case 'RUN_STARTED':
348
- context.setCurrentMessageId(generateMessageId());
349
- context.resetContent();
416
+ if (!context.getCurrentMessageId()) {
417
+ context.setCurrentMessageId(generateMessageId());
418
+ }
419
+ if (!context.getCurrentContent()) {
420
+ context.resetContent();
421
+ }
350
422
  break;
351
423
  case 'TEXT_MESSAGE_START': {
352
424
  const messageId = event.messageId;
353
- context.setCurrentMessageId(messageId || generateMessageId());
354
- context.resetContent();
425
+ if (!context.getCurrentMessageId()) {
426
+ context.setCurrentMessageId(messageId || generateMessageId());
427
+ }
428
+ if (!context.getCurrentContent()) {
429
+ context.resetContent();
430
+ }
355
431
  break;
356
432
  }
357
433
  case 'TEXT_MESSAGE_CONTENT': {
@@ -359,6 +435,7 @@ export class AGUIAdapter extends BaseProtocolAdapter {
359
435
  const delta = event.delta;
360
436
  if (delta) {
361
437
  context.appendContent(delta);
438
+ context.appendTurnContent(delta);
362
439
  const message = createAssistantMessage(context.getCurrentContent());
363
440
  message.id = context.getCurrentMessageId() || generateMessageId();
364
441
  this.emit({
@@ -372,8 +449,10 @@ export class AGUIAdapter extends BaseProtocolAdapter {
372
449
  case 'TEXT_MESSAGE_END': {
373
450
  const finalMessage = createAssistantMessage(context.getCurrentContent());
374
451
  finalMessage.id = context.getCurrentMessageId() || generateMessageId();
375
- // Store the assistant content for tool result continuation
452
+ // Store assistant content and message ID for continuations
376
453
  this.lastAssistantContent = context.getCurrentContent();
454
+ // Store just this turn's text for the message history
455
+ this.lastTurnContent = context.getCurrentTurnContent();
377
456
  this.emit({
378
457
  type: 'message',
379
458
  message: finalMessage,
@@ -55,8 +55,11 @@ export interface FrontendToolDefinition<TArgs = Record<string, unknown>, TResult
55
55
  name: string;
56
56
  /** Description for the LLM */
57
57
  description: string;
58
- /** Parameter definitions */
59
- parameters: ToolParameter[];
58
+ /**
59
+ * Parameter definitions.
60
+ * Accepts either CopilotKit-style ToolParameter[] or JSON Schema format.
61
+ */
62
+ parameters: ToolParameter[] | Record<string, unknown>;
60
63
  /**
61
64
  * Execution location
62
65
  * @default 'frontend'
@@ -1,24 +1,7 @@
1
1
  export * from './chat';
2
2
  export type { ToolCallStatus } from './chat/types/message';
3
3
  export type { ToolCallStatus as DisplayToolCallStatus } from './chat/components/base/ChatBase';
4
- export { MockFileBrowser } from './MockFileBrowser';
5
- export type { MockFileBrowserProps } from './MockFileBrowser';
6
- export { MainContent } from './MainContent';
7
- export type { MainContentProps } from './MainContent';
8
- export { SessionTabs } from './SessionTabs';
9
- export type { SessionTabsProps, Session } from './SessionTabs';
10
- export { Header } from './Header';
11
- export type { HeaderProps } from './Header';
12
- export { HeaderControls } from './HeaderControls';
13
- export type { HeaderControlsProps } from './HeaderControls';
14
- export { FooterMetrics } from './FooterMetrics';
15
- export type { FooterMetricsProps } from './FooterMetrics';
16
- export { TimeTravel } from './TimeTravel';
17
- export type { TimeTravelProps } from './TimeTravel';
18
- export { LexicalEditor } from './LexicalEditor';
19
- export type { LexicalEditorProps } from './LexicalEditor';
20
4
  export { AgentConfiguration, AGENT_LIBRARIES, TRANSPORTS, EXTENSIONS, isSpecSelection, getSpecId, } from './AgentConfiguration';
21
- export type { AgentLibrary, Transport, Extension, AgentConfigurationProps, SkillOption, MCPServerConfig, MCPServerTool, LibraryAgentSpec, } from './AgentConfiguration';
5
+ export type { AgentLibrary, Transport, Extension, AgentConfigurationProps, SkillOption, MCPServerTool, LibraryAgentSpec, } from './AgentConfiguration';
22
6
  export { McpServerManager } from './McpServerManager';
23
7
  export type { McpServerSelection, McpServerManagerProps, } from './McpServerManager';
24
- export type { Agent as ExampleAgent, AgentStatus as ExampleAgentStatus, AgentsState, Transport as ExampleTransport, } from '../examples/stores/examplesStore';
@@ -4,14 +4,5 @@
4
4
  */
5
5
  // Primary exports from chat (next-gen chat component)
6
6
  export * from './chat';
7
- // Example/layout components
8
- export { MockFileBrowser } from './MockFileBrowser';
9
- export { MainContent } from './MainContent';
10
- export { SessionTabs } from './SessionTabs';
11
- export { Header } from './Header';
12
- export { HeaderControls } from './HeaderControls';
13
- export { FooterMetrics } from './FooterMetrics';
14
- export { TimeTravel } from './TimeTravel';
15
- export { LexicalEditor } from './LexicalEditor';
16
7
  export { AgentConfiguration, AGENT_LIBRARIES, TRANSPORTS, EXTENSIONS, isSpecSelection, getSpecId, } from './AgentConfiguration';
17
8
  export { McpServerManager } from './McpServerManager';
@@ -1,5 +1 @@
1
- export * from './envvars';
2
- export * from './mcpServers';
3
- export * from './agents';
4
- export * from './skills';
5
1
  export * from './utils';
@@ -2,8 +2,4 @@
2
2
  * Copyright (c) 2025-2026 Datalayer, Inc.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
- export * from './envvars';
6
- export * from './mcpServers';
7
- export * from './agents';
8
- export * from './skills';
9
5
  export * from './utils';
@@ -278,7 +278,7 @@ const A2UiRestaurantExample = () => {
278
278
  console.log('A2UI Action:', action);
279
279
  // Actions are handled in the content component
280
280
  }, []);
281
- return (_jsx(DatalayerThemeProvider, { colorMode: "day", children: _jsx(A2UIProvider, { onAction: handleAction, children: _jsxs(Box, { sx: {
281
+ return (_jsx(DatalayerThemeProvider, { children: _jsx(A2UIProvider, { onAction: handleAction, children: _jsxs(Box, { sx: {
282
282
  display: 'flex',
283
283
  flexDirection: 'column',
284
284
  minHeight: '100vh',
@@ -0,0 +1,15 @@
1
+ /**
2
+ * AgentRuntimeChatExample
3
+ *
4
+ * Demonstrates the unified Chat component with automatic agent creation.
5
+ * On mount, it creates an agent from the codeai/simple spec via the
6
+ * REST API, then renders a full-page Chat interface.
7
+ *
8
+ * This mirrors how agent.html works but inside the examples runner,
9
+ * without requiring a CLI `--agent-id` flag at server startup.
10
+ *
11
+ * Backend: POST /api/v1/agents → /api/v1/ag-ui/{agentId}/
12
+ */
13
+ import React from 'react';
14
+ declare const AgentRuntimeChatExample: React.FC;
15
+ export default AgentRuntimeChatExample;
@@ -0,0 +1,126 @@
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
+ * AgentRuntimeChatExample
8
+ *
9
+ * Demonstrates the unified Chat component with automatic agent creation.
10
+ * On mount, it creates an agent from the codeai/simple spec via the
11
+ * REST API, then renders a full-page Chat interface.
12
+ *
13
+ * This mirrors how agent.html works but inside the examples runner,
14
+ * without requiring a CLI `--agent-id` flag at server startup.
15
+ *
16
+ * Backend: POST /api/v1/agents → /api/v1/ag-ui/{agentId}/
17
+ */
18
+ import { useEffect, useState } from 'react';
19
+ import { Text, Spinner } from '@primer/react';
20
+ import { AlertIcon } from '@primer/octicons-react';
21
+ import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
22
+ import { DatalayerThemeProvider } from '@datalayer/core';
23
+ import { Chat } from '../components/chat';
24
+ setupPrimerPortals();
25
+ const BASE_URL = 'http://localhost:8765';
26
+ const AGENT_SPEC_ID = 'codeai/simple';
27
+ const AGENT_NAME = 'simple';
28
+ const AgentRuntimeChatExample = () => {
29
+ const [agentId, setAgentId] = useState(null);
30
+ const [error, setError] = useState(null);
31
+ const [isCreating, setIsCreating] = useState(true);
32
+ // Create the agent on mount
33
+ useEffect(() => {
34
+ let cancelled = false;
35
+ const ensureAgent = async () => {
36
+ try {
37
+ // First, check if the agent already exists
38
+ const checkResponse = await fetch(`${BASE_URL}/api/v1/agents/${encodeURIComponent(AGENT_NAME)}`);
39
+ if (checkResponse.ok) {
40
+ // Agent exists — reuse it (preserves conversation history)
41
+ if (!cancelled) {
42
+ setAgentId(AGENT_NAME);
43
+ setIsCreating(false);
44
+ }
45
+ return;
46
+ }
47
+ // Agent doesn't exist — create it from the library spec
48
+ const response = await fetch(`${BASE_URL}/api/v1/agents`, {
49
+ method: 'POST',
50
+ headers: { 'Content-Type': 'application/json' },
51
+ body: JSON.stringify({
52
+ name: AGENT_NAME,
53
+ agent_spec_id: AGENT_SPEC_ID,
54
+ transport: 'ag-ui',
55
+ }),
56
+ });
57
+ if (!response.ok) {
58
+ const data = await response
59
+ .json()
60
+ .catch(() => ({ detail: 'Unknown error' }));
61
+ // Race condition: agent was created between our check and POST
62
+ if (response.status === 400 &&
63
+ data.detail?.includes('already exists')) {
64
+ if (!cancelled) {
65
+ setAgentId(AGENT_NAME);
66
+ setIsCreating(false);
67
+ }
68
+ return;
69
+ }
70
+ throw new Error(data.detail || `Failed to create agent: ${response.status}`);
71
+ }
72
+ const data = await response.json();
73
+ if (!cancelled) {
74
+ setAgentId(data.id);
75
+ setIsCreating(false);
76
+ }
77
+ }
78
+ catch (err) {
79
+ if (!cancelled) {
80
+ setError(err instanceof Error ? err.message : 'Failed to create agent');
81
+ setIsCreating(false);
82
+ }
83
+ }
84
+ };
85
+ ensureAgent();
86
+ return () => {
87
+ cancelled = true;
88
+ };
89
+ }, []);
90
+ // Loading state while agent is being created
91
+ if (isCreating) {
92
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
93
+ display: 'flex',
94
+ flexDirection: 'column',
95
+ alignItems: 'center',
96
+ justifyContent: 'center',
97
+ height: '100vh',
98
+ gap: 3,
99
+ bg: 'canvas.default',
100
+ }, children: [_jsx(Spinner, { size: "large" }), _jsxs(Text, { sx: { color: 'fg.muted' }, children: ["Creating agent from ", AGENT_SPEC_ID, "..."] })] }) }));
101
+ }
102
+ // Error state
103
+ if (error || !agentId) {
104
+ return (_jsx(DatalayerThemeProvider, { children: _jsxs(Box, { sx: {
105
+ display: 'flex',
106
+ flexDirection: 'column',
107
+ alignItems: 'center',
108
+ justifyContent: 'center',
109
+ height: '100vh',
110
+ gap: 3,
111
+ bg: 'canvas.default',
112
+ }, children: [_jsx(AlertIcon, { size: 48 }), _jsx(Text, { sx: { color: 'danger.fg', fontSize: 2 }, children: "Failed to start agent" }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: error || 'No agent ID returned' })] }) }));
113
+ }
114
+ // Agent is ready — render the Chat component
115
+ return (_jsx(Chat, { transport: "ag-ui", baseUrl: BASE_URL, agentId: agentId, title: "Simple Agent", placeholder: "Send a message...", description: "Chat with a simple AI assistant", showHeader: true, showModelSelector: true, showToolsMenu: true, showSkillsMenu: true, showTokenUsage: true, showInformation: true, autoFocus: true, height: "100vh", runtimeId: agentId, historyEndpoint: `${BASE_URL}/api/v1/history`, suggestions: [
116
+ {
117
+ title: 'Hello',
118
+ message: 'Hello, what can you do?',
119
+ },
120
+ {
121
+ title: 'Help',
122
+ message: 'What tools do you have available?',
123
+ },
124
+ ], submitOnSuggestionClick: true }));
125
+ };
126
+ export default AgentRuntimeChatExample;
@@ -54,7 +54,7 @@ type IdentityProviderInput = OAuthProviderInput | TokenProviderInput;
54
54
  type IdentityProvidersInput = {
55
55
  [provider: string]: IdentityProviderInput;
56
56
  };
57
- type AgentSpaceFormExampleProps = {
57
+ type AgentRuntimeFormExampleProps = {
58
58
  initialWsUrl?: string;
59
59
  initialBaseUrl?: string;
60
60
  initialAgentName?: string;
@@ -86,5 +86,5 @@ type AgentSpaceFormExampleProps = {
86
86
  /** @deprecated Use identityProviders instead */
87
87
  kaggleToken?: string;
88
88
  };
89
- declare const AgentSpaceFormExample: React.FC<AgentSpaceFormExampleProps>;
90
- export default AgentSpaceFormExample;
89
+ declare const AgentRuntimeFormExample: React.FC<AgentRuntimeFormExampleProps>;
90
+ export default AgentRuntimeFormExample;