@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.
- package/README.md +2 -2
- package/lib/Agent.d.ts +29 -0
- package/lib/Agent.js +131 -0
- package/lib/AgentLexical.d.ts +34 -0
- package/lib/AgentLexical.js +296 -0
- package/lib/AgentNotebook.d.ts +19 -0
- package/lib/AgentNotebook.js +192 -0
- package/lib/agent-lexical-main.d.ts +1 -0
- package/lib/agent-lexical-main.js +11 -0
- package/lib/agent-main.d.ts +1 -0
- package/lib/agent-main.js +11 -0
- package/lib/agent-notebook-main.d.ts +1 -0
- package/lib/agent-notebook-main.js +12 -0
- package/lib/components/AgentConfiguration.d.ts +4 -22
- package/lib/components/AgentConfiguration.js +8 -8
- package/lib/components/chat/components/AgentDetails.d.ts +3 -1
- package/lib/components/chat/components/AgentDetails.js +6 -6
- package/lib/components/chat/components/Chat.d.ts +29 -3
- package/lib/components/chat/components/Chat.js +64 -59
- package/lib/components/chat/components/ChatFloating.d.ts +34 -12
- package/lib/components/chat/components/ChatFloating.js +54 -21
- package/lib/components/chat/components/ChatInline.d.ts +5 -1
- package/lib/components/chat/components/ChatInline.js +8 -1
- package/lib/components/chat/components/ChatSidebar.d.ts +6 -1
- package/lib/components/chat/components/ChatSidebar.js +2 -2
- package/lib/components/chat/components/ChatStandalone.d.ts +6 -1
- package/lib/components/chat/components/ChatStandalone.js +2 -2
- package/lib/components/chat/components/base/ChatBase.d.ts +49 -8
- package/lib/components/chat/components/base/ChatBase.js +544 -149
- package/lib/components/chat/components/base/InputPrompt.d.ts +42 -0
- package/lib/components/chat/components/base/InputPrompt.js +131 -0
- package/lib/components/chat/components/index.d.ts +3 -3
- package/lib/components/chat/components/index.js +1 -1
- package/lib/components/chat/components/parts/ReasoningPart.js +2 -4
- package/lib/components/chat/components/parts/TextPart.js +2 -70
- package/lib/components/chat/components/styles/streamdownStyles.d.ts +23 -0
- package/lib/components/chat/components/styles/streamdownStyles.js +319 -0
- package/lib/components/chat/index.d.ts +1 -1
- package/lib/components/chat/index.js +1 -1
- package/lib/components/chat/inference/DatalayerInferenceProvider.js +16 -12
- package/lib/components/chat/inference/SelfHostedInferenceProvider.js +16 -12
- package/lib/components/chat/protocols/AGUIAdapter.d.ts +10 -3
- package/lib/components/chat/protocols/AGUIAdapter.js +123 -44
- package/lib/components/chat/types/tool.d.ts +5 -2
- package/lib/components/index.d.ts +1 -18
- package/lib/components/index.js +0 -9
- package/lib/config/index.d.ts +0 -4
- package/lib/config/index.js +0 -4
- package/lib/examples/A2UiRestaurantExample.js +1 -1
- package/lib/examples/AgentRuntimeChatExample.d.ts +15 -0
- package/lib/examples/AgentRuntimeChatExample.js +126 -0
- package/lib/examples/{AgentSpaceFormExample.d.ts → AgentRuntimeFormExample.d.ts} +3 -3
- package/lib/examples/{AgentSpaceFormExample.js → AgentRuntimeFormExample.js} +10 -8
- package/lib/examples/AgentRuntimeLexicalExample.js +6 -3
- package/lib/examples/AgentRuntimeLexicalSidebarExample.js +8 -1
- package/lib/examples/AgentRuntimeNotebookExample.js +6 -5
- package/lib/examples/CopilotKitNotebookExample.js +2 -2
- package/lib/examples/JupyterNotebookExample.js +2 -2
- package/lib/{components → examples/components}/Header.d.ts +2 -1
- package/lib/{components → examples/components}/HeaderControls.js +1 -1
- package/lib/{components → examples/components}/LexicalEditor.d.ts +6 -1
- package/lib/{components → examples/components}/LexicalEditor.js +4 -4
- package/lib/{components → examples/components}/MainContent.d.ts +1 -1
- package/lib/{components → examples/components}/MainContent.js +7 -5
- package/lib/examples/components/index.d.ts +16 -0
- package/lib/examples/components/index.js +13 -0
- package/lib/examples/example-selector.js +2 -1
- package/lib/examples/index.d.ts +1 -1
- package/lib/examples/index.js +1 -1
- package/lib/examples/main.js +2 -2
- package/lib/examples/stores/examplesStore.d.ts +2 -23
- package/lib/index.d.ts +2 -1
- package/lib/index.js +1 -0
- package/lib/lexical/ChatInlinePlugin.d.ts +13 -2
- package/lib/lexical/ChatInlinePlugin.js +41 -179
- package/lib/lexical/index.d.ts +1 -0
- package/lib/lexical/index.js +1 -0
- package/lib/lexical/useChatInlineToolbarItems.d.ts +28 -0
- package/lib/lexical/useChatInlineToolbarItems.js +163 -0
- package/lib/runtime/useAgentRuntime.d.ts +1 -1
- package/lib/runtime/useAgentRuntime.js +1 -1
- package/lib/{config/agents/code-ai → specs/agents/codeai}/agents.d.ts +5 -2
- package/lib/specs/agents/codeai/agents.js +151 -0
- package/lib/{config → specs}/agents/codemode-paper/agents.d.ts +4 -2
- package/lib/{config → specs}/agents/codemode-paper/agents.js +39 -19
- package/lib/{config → specs}/agents/datalayer-ai/agents.d.ts +4 -2
- package/lib/{config → specs}/agents/datalayer-ai/agents.js +17 -2
- package/lib/{config → specs}/agents/index.d.ts +3 -1
- package/lib/{config → specs}/agents/index.js +12 -3
- package/lib/{config → specs}/envvars.d.ts +1 -0
- package/lib/{config → specs}/envvars.js +10 -0
- package/lib/specs/index.d.ts +5 -0
- package/lib/specs/index.js +9 -0
- package/lib/{config → specs}/mcpServers.d.ts +2 -1
- package/lib/{config → specs}/mcpServers.js +23 -1
- package/lib/specs/models.d.ts +68 -0
- package/lib/specs/models.js +239 -0
- package/lib/state/substates/AIAgentState.d.ts +0 -1
- package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.d.ts +11 -22
- package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.js +5 -5
- package/lib/tools/adapters/agent-runtimes/lexicalHooks.d.ts +6 -6
- package/lib/tools/adapters/agent-runtimes/lexicalHooks.js +4 -4
- package/lib/tools/adapters/agent-runtimes/notebookHooks.d.ts +6 -6
- package/lib/tools/adapters/agent-runtimes/notebookHooks.js +4 -4
- package/lib/{types.d.ts → types/Types.d.ts} +32 -6
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +1 -0
- package/package.json +11 -5
- package/scripts/codegen/generate_agents.py +53 -13
- package/scripts/codegen/generate_envvars.py +1 -1
- package/scripts/codegen/generate_mcp_servers.py +5 -5
- package/scripts/codegen/generate_models.py +486 -0
- package/scripts/codegen/generate_skills.py +2 -2
- package/style/primer-primitives.css +22 -0
- package/lib/components/chat/components/elements/ChatInputPrompt.d.ts +0 -37
- package/lib/components/chat/components/elements/ChatInputPrompt.js +0 -150
- package/lib/config/agents/code-ai/agents.js +0 -70
- /package/lib/{components → examples/components}/FooterMetrics.d.ts +0 -0
- /package/lib/{components → examples/components}/FooterMetrics.js +0 -0
- /package/lib/{components → examples/components}/Header.js +0 -0
- /package/lib/{components → examples/components}/HeaderControls.d.ts +0 -0
- /package/lib/{components → examples/components}/MockFileBrowser.d.ts +0 -0
- /package/lib/{components → examples/components}/MockFileBrowser.js +0 -0
- /package/lib/{components → examples/components}/SessionTabs.d.ts +0 -0
- /package/lib/{components → examples/components}/SessionTabs.js +0 -0
- /package/lib/{components → examples/components}/TimeTravel.d.ts +0 -0
- /package/lib/{components → examples/components}/TimeTravel.js +0 -0
- /package/lib/{config/agents/code-ai → specs/agents/codeai}/index.d.ts +0 -0
- /package/lib/{config/agents/code-ai → specs/agents/codeai}/index.js +0 -0
- /package/lib/{config → specs}/agents/codemode-paper/index.d.ts +0 -0
- /package/lib/{config → specs}/agents/codemode-paper/index.js +0 -0
- /package/lib/{config → specs}/agents/datalayer-ai/index.d.ts +0 -0
- /package/lib/{config → specs}/agents/datalayer-ai/index.js +0 -0
- /package/lib/{config → specs}/skills.d.ts +0 -0
- /package/lib/{config → specs}/skills.js +0 -0
- /package/lib/{types.js → types/Types.js} +0 -0
|
@@ -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,
|
|
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,
|
|
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
|
-
|
|
265
|
-
|
|
266
|
-
p
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
p
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
*
|
|
71
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
190
|
-
*
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
217
|
-
|
|
218
|
-
|
|
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
|
|
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
|
|
234
|
-
const
|
|
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
|
-
//
|
|
283
|
+
}));
|
|
284
|
+
// 7. Assemble full continuation history
|
|
248
285
|
const continuationMessages = [
|
|
249
286
|
...this.messageHistory,
|
|
250
|
-
|
|
251
|
-
|
|
287
|
+
assistantMessageWithToolCalls,
|
|
288
|
+
...toolResultMessages,
|
|
252
289
|
];
|
|
253
|
-
//
|
|
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
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
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.
|
|
349
|
-
|
|
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.
|
|
354
|
-
|
|
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
|
|
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
|
-
/**
|
|
59
|
-
|
|
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,
|
|
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';
|
package/lib/components/index.js
CHANGED
|
@@ -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';
|
package/lib/config/index.d.ts
CHANGED
package/lib/config/index.js
CHANGED
|
@@ -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, {
|
|
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
|
|
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
|
|
90
|
-
export default
|
|
89
|
+
declare const AgentRuntimeFormExample: React.FC<AgentRuntimeFormExampleProps>;
|
|
90
|
+
export default AgentRuntimeFormExample;
|