@datalayer/agent-runtimes 1.0.3 → 1.0.4
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 +13 -131
- package/lib/chat/Chat.d.ts +3 -1
- package/lib/chat/Chat.js +2 -2
- package/lib/chat/base/ChatBase.js +52 -1
- package/lib/chat/messages/ChatMessageList.js +17 -4
- package/lib/client/AgentsMixin.d.ts +48 -1
- package/lib/client/AgentsMixin.js +109 -0
- package/lib/components/NotificationEventCard.js +51 -26
- package/lib/components/OutputCard.js +21 -7
- package/lib/components/ToolApprovalCard.js +20 -2
- package/lib/examples/AgentCheckpointsExample.js +2 -8
- package/lib/examples/AgentCodemodeExample.js +3 -9
- package/lib/examples/AgentEvalsExample.js +3 -9
- package/lib/examples/AgentGuardrailsExample.js +3 -9
- package/lib/examples/AgentMemoryExample.js +3 -9
- package/lib/examples/AgentMonitoringExample.js +3 -9
- package/lib/examples/AgentNotificationsExample.js +2 -8
- package/lib/examples/AgentOutputsExample.js +3 -9
- package/lib/examples/AgentSandboxExample.js +3 -9
- package/lib/examples/AgentSkillsExample.js +3 -9
- package/lib/examples/AgentToolApprovalsExample.js +89 -24
- package/lib/examples/AgentTriggersExample.js +604 -37
- package/lib/examples/ChatExample.js +2 -10
- package/lib/examples/components/ErrorView.d.ts +14 -0
- package/lib/examples/components/ErrorView.js +20 -0
- package/lib/examples/components/index.d.ts +2 -0
- package/lib/examples/components/index.js +1 -0
- package/lib/examples/main.d.ts +1 -0
- package/lib/examples/main.js +1 -0
- package/lib/protocols/VercelAIAdapter.d.ts +2 -0
- package/lib/protocols/VercelAIAdapter.js +86 -20
- package/lib/shims/json5.d.ts +4 -0
- package/lib/shims/json5.js +8 -0
- package/lib/specs/agents/agents.js +241 -1390
- package/lib/specs/agents/index.js +1 -3
- package/lib/specs/envvars.js +20 -27
- package/lib/specs/evals.js +6 -6
- package/lib/specs/events.d.ts +10 -2
- package/lib/specs/events.js +84 -126
- package/lib/specs/frontendTools.js +2 -2
- package/lib/specs/guardrails.d.ts +7 -0
- package/lib/specs/guardrails.js +159 -240
- package/lib/specs/mcpServers.js +6 -35
- package/lib/specs/memory.d.ts +2 -0
- package/lib/specs/memory.js +17 -4
- package/lib/specs/models.js +5 -25
- package/lib/specs/notifications.js +18 -102
- package/lib/specs/outputs.js +9 -15
- package/lib/specs/skills.js +18 -18
- package/lib/specs/teams/index.js +1 -3
- package/lib/specs/teams/teams.js +348 -468
- package/lib/specs/tools.js +6 -3
- package/lib/specs/triggers.js +11 -61
- package/lib/types/tools.d.ts +2 -0
- package/package.json +1 -1
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
- package/scripts/codegen/generate_agents.py +4 -1
- package/scripts/codegen/generate_events.py +12 -4
- package/scripts/codegen/generate_tools.py +20 -0
- package/style/primer-primitives.css +1 -6
- package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_envvars.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_guardrails.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_mcp_servers.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_memory.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_models.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_notifications.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_outputs.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_skills.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_teams.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_tools.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_triggers.cpython-313.pyc +0 -0
|
@@ -17,9 +17,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
17
17
|
*/
|
|
18
18
|
import { useEffect, useState } from 'react';
|
|
19
19
|
import { Text, Spinner } from '@primer/react';
|
|
20
|
-
import { AlertIcon } from '@primer/octicons-react';
|
|
21
20
|
import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
|
|
22
21
|
import { ThemedProvider } from './utils/themedProvider';
|
|
22
|
+
import { ErrorView } from './components';
|
|
23
23
|
import { Chat } from '../chat';
|
|
24
24
|
setupPrimerPortals();
|
|
25
25
|
const BASE_URL = 'http://localhost:8765';
|
|
@@ -101,15 +101,7 @@ const AgentRuntimeChatExample = () => {
|
|
|
101
101
|
}
|
|
102
102
|
// Error state
|
|
103
103
|
if (error || !agentId) {
|
|
104
|
-
return (_jsx(ThemedProvider, { children:
|
|
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' })] }) }));
|
|
104
|
+
return (_jsx(ThemedProvider, { children: _jsx(ErrorView, { error: "Failed to start agent", detail: error || 'No agent ID returned' }) }));
|
|
113
105
|
}
|
|
114
106
|
// Agent is ready — render the Chat component
|
|
115
107
|
return (_jsx(Chat, { protocol: "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: [
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type ErrorViewProps = {
|
|
3
|
+
/** Primary error message. Falls back to "Agent failed to start". */
|
|
4
|
+
error?: string | null;
|
|
5
|
+
/** Optional secondary detail line shown below the primary message. */
|
|
6
|
+
detail?: string | null;
|
|
7
|
+
/** Called when the user clicks "Sign out". Button only appears for 401 errors. */
|
|
8
|
+
onLogout?: () => void;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Full-screen error view used by examples when agent creation fails.
|
|
12
|
+
* Automatically shows a "Sign out" button when the error contains "401".
|
|
13
|
+
*/
|
|
14
|
+
export declare const ErrorView: React.FC<ErrorViewProps>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Text, Button } from '@primer/react';
|
|
3
|
+
import { AlertIcon, SignOutIcon } from '@primer/octicons-react';
|
|
4
|
+
import { Box } from '@datalayer/primer-addons';
|
|
5
|
+
/**
|
|
6
|
+
* Full-screen error view used by examples when agent creation fails.
|
|
7
|
+
* Automatically shows a "Sign out" button when the error contains "401".
|
|
8
|
+
*/
|
|
9
|
+
export const ErrorView = ({ error, detail, onLogout, }) => {
|
|
10
|
+
const message = error || 'Agent failed to start';
|
|
11
|
+
const is401 = String(message).includes('401') || String(detail || '').includes('401');
|
|
12
|
+
return (_jsxs(Box, { sx: {
|
|
13
|
+
display: 'flex',
|
|
14
|
+
flexDirection: 'column',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
justifyContent: 'center',
|
|
17
|
+
height: '100vh',
|
|
18
|
+
gap: 3,
|
|
19
|
+
}, children: [_jsx(AlertIcon, { size: 48 }), _jsx(Text, { sx: { color: 'danger.fg', fontSize: 2 }, children: message }), detail && _jsx(Text, { sx: { color: 'fg.muted' }, children: detail }), is401 && onLogout && (_jsx(Button, { variant: "danger", leadingVisual: SignOutIcon, onClick: onLogout, children: "Sign out" }))] }));
|
|
20
|
+
};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
// Example/layout components
|
|
6
|
+
export { ErrorView } from './ErrorView';
|
|
6
7
|
export { MockFileBrowser } from './MockFileBrowser';
|
|
7
8
|
export { MainContent } from './MainContent';
|
|
8
9
|
export { SessionTabs } from './SessionTabs';
|
package/lib/examples/main.d.ts
CHANGED
package/lib/examples/main.js
CHANGED
|
@@ -17,6 +17,7 @@ import { EXAMPLES } from './example-selector';
|
|
|
17
17
|
import { useExampleThemeStore } from './utils/themeStore';
|
|
18
18
|
import { ExampleWrapper } from './components/ExampleWrapper';
|
|
19
19
|
import nbformatExample from './utils/notebooks/NotebookExample1.ipynb.json';
|
|
20
|
+
import '../../style/primer-primitives.css';
|
|
20
21
|
// Load configurations from DOM
|
|
21
22
|
const loadConfigurations = () => {
|
|
22
23
|
// Load Datalayer configuration
|
|
@@ -42,7 +42,9 @@ export declare class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
42
42
|
private messageHistory;
|
|
43
43
|
private lastAssistantText;
|
|
44
44
|
private lastTools;
|
|
45
|
+
private lastFrontendToolNames;
|
|
45
46
|
private isContinuation;
|
|
47
|
+
private deferredToolMeta;
|
|
46
48
|
private _streamParsingDepth;
|
|
47
49
|
private _streamDonePromise;
|
|
48
50
|
private _streamDoneResolve;
|
|
@@ -22,7 +22,13 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
22
22
|
messageHistory = [];
|
|
23
23
|
lastAssistantText = '';
|
|
24
24
|
lastTools = [];
|
|
25
|
+
lastFrontendToolNames = new Set();
|
|
25
26
|
isContinuation = false;
|
|
27
|
+
// Metadata for ALL deferred tool calls (frontend + approval), keyed by toolCallId.
|
|
28
|
+
// Unlike pendingToolCalls (which only tracks frontend tools for batching),
|
|
29
|
+
// this preserves tool name/args for approval tools so sendToolResult can
|
|
30
|
+
// build a correct continuation message.
|
|
31
|
+
deferredToolMeta = new Map();
|
|
26
32
|
// Stream parsing depth — prevents premature continuations
|
|
27
33
|
_streamParsingDepth = 0;
|
|
28
34
|
_streamDonePromise = null;
|
|
@@ -97,10 +103,17 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
97
103
|
// Store tools for potential continuation
|
|
98
104
|
if (options?.tools) {
|
|
99
105
|
this.lastTools = options.tools;
|
|
106
|
+
this.lastFrontendToolNames = new Set(options.tools
|
|
107
|
+
.map(t => t?.name)
|
|
108
|
+
.filter((name) => Boolean(name)));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
this.lastFrontendToolNames = new Set();
|
|
100
112
|
}
|
|
101
113
|
// Reset assistant content tracking for fresh (non-continuation) messages
|
|
102
114
|
if (!this.isContinuation) {
|
|
103
115
|
this.lastAssistantText = '';
|
|
116
|
+
this.deferredToolMeta.clear();
|
|
104
117
|
}
|
|
105
118
|
try {
|
|
106
119
|
let vercelMessages;
|
|
@@ -156,6 +169,9 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
156
169
|
const requestBody = {
|
|
157
170
|
id: requestId,
|
|
158
171
|
messages: vercelMessages,
|
|
172
|
+
// Required for pydantic-ai deferred tool approval continuations.
|
|
173
|
+
// sdkVersion 6 enables parsing approval-responded tool parts.
|
|
174
|
+
sdkVersion: 6,
|
|
159
175
|
trigger: 'submit-message',
|
|
160
176
|
...(options?.tools && { tools: options.tools }),
|
|
161
177
|
...(options?.model && { model: options.model }),
|
|
@@ -439,12 +455,9 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
439
455
|
event.tool?.name;
|
|
440
456
|
const args = normalizeToolArgs(event.input || event.args || event.arguments, pending?.inputText || '');
|
|
441
457
|
if (toolName) {
|
|
442
|
-
//
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
toolName,
|
|
446
|
-
args,
|
|
447
|
-
});
|
|
458
|
+
// Emit tool-call for all tools so UI can render a tool entry.
|
|
459
|
+
// Only client-declared frontend tools should participate in
|
|
460
|
+
// frontend continuation batching via pendingToolCalls.
|
|
448
461
|
this.emit({
|
|
449
462
|
type: 'tool-call',
|
|
450
463
|
toolCall: {
|
|
@@ -454,6 +467,20 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
454
467
|
},
|
|
455
468
|
timestamp: new Date(),
|
|
456
469
|
});
|
|
470
|
+
// Track metadata for ALL deferred tools so sendToolResult
|
|
471
|
+
// can build proper continuation messages (tool name + args).
|
|
472
|
+
this.deferredToolMeta.set(toolCallId, {
|
|
473
|
+
toolCallId,
|
|
474
|
+
toolName,
|
|
475
|
+
args,
|
|
476
|
+
});
|
|
477
|
+
if (this.lastFrontendToolNames.has(toolName)) {
|
|
478
|
+
this.pendingToolCalls.set(toolCallId, {
|
|
479
|
+
toolCallId,
|
|
480
|
+
toolName,
|
|
481
|
+
args,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
457
484
|
}
|
|
458
485
|
}
|
|
459
486
|
else if (event.type === 'tool-output-available') {
|
|
@@ -475,6 +502,7 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
475
502
|
// Server already executed this tool — remove from pending
|
|
476
503
|
// frontend tool calls so emitDoneOnce is not blocked.
|
|
477
504
|
this.pendingToolCalls.delete(toolCallId);
|
|
505
|
+
this.deferredToolMeta.delete(toolCallId);
|
|
478
506
|
}
|
|
479
507
|
else if (event.type === 'tool-output-error' ||
|
|
480
508
|
event.type === 'tool-error') {
|
|
@@ -489,6 +517,7 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
489
517
|
// Server handled the error — clear from pending frontend
|
|
490
518
|
// tool calls so emitDoneOnce is not blocked.
|
|
491
519
|
this.pendingToolCalls.delete(toolCallId);
|
|
520
|
+
this.deferredToolMeta.delete(toolCallId);
|
|
492
521
|
this.emit({
|
|
493
522
|
type: 'tool-result',
|
|
494
523
|
toolResult: {
|
|
@@ -575,8 +604,10 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
575
604
|
toolResult: result,
|
|
576
605
|
timestamp: new Date(),
|
|
577
606
|
});
|
|
578
|
-
// 2. Retrieve tool metadata from pending map
|
|
579
|
-
|
|
607
|
+
// 2. Retrieve tool metadata from pending map (frontend tools) or
|
|
608
|
+
// deferred tool meta (approval / all deferred tools).
|
|
609
|
+
const pendingToolCall = this.pendingToolCalls.get(toolCallId) ??
|
|
610
|
+
this.deferredToolMeta.get(toolCallId);
|
|
580
611
|
if (!pendingToolCall) {
|
|
581
612
|
console.warn('[VercelAIAdapter] No pending tool call found for ID:', toolCallId);
|
|
582
613
|
}
|
|
@@ -613,18 +644,53 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
613
644
|
state: 'done',
|
|
614
645
|
});
|
|
615
646
|
}
|
|
616
|
-
// Add each tool call with its result as a
|
|
647
|
+
// Add each tool call with its result as a dynamic-tool part.
|
|
648
|
+
// pydantic-ai parses DynamicTool* parts with output-available / output-error
|
|
649
|
+
// and approval-responded states for deferred approval continuations.
|
|
617
650
|
for (const tr of this.collectedToolResults.values()) {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
651
|
+
const resultObj = tr.result.result && typeof tr.result.result === 'object'
|
|
652
|
+
? tr.result.result
|
|
653
|
+
: undefined;
|
|
654
|
+
const isApprovalDecision = !!resultObj && typeof resultObj.approved === 'boolean';
|
|
655
|
+
if (isApprovalDecision) {
|
|
656
|
+
const approvalId = typeof resultObj?.approvalId === 'string'
|
|
657
|
+
? resultObj.approvalId
|
|
658
|
+
: tr.toolCallId;
|
|
659
|
+
const approved = Boolean(resultObj?.approved);
|
|
660
|
+
const reason = typeof resultObj?.message === 'string' ? resultObj.message : undefined;
|
|
661
|
+
assistantParts.push({
|
|
662
|
+
type: 'dynamic-tool',
|
|
663
|
+
toolName: tr.toolName,
|
|
664
|
+
toolCallId: tr.toolCallId,
|
|
665
|
+
state: 'approval-responded',
|
|
666
|
+
input: tr.args,
|
|
667
|
+
approval: {
|
|
668
|
+
id: approvalId,
|
|
669
|
+
approved,
|
|
670
|
+
...(reason ? { reason } : {}),
|
|
671
|
+
},
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
else if (tr.result.success) {
|
|
675
|
+
assistantParts.push({
|
|
676
|
+
type: 'dynamic-tool',
|
|
677
|
+
toolName: tr.toolName,
|
|
678
|
+
toolCallId: tr.toolCallId,
|
|
679
|
+
state: 'output-available',
|
|
680
|
+
input: tr.args,
|
|
681
|
+
output: tr.result.result,
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
assistantParts.push({
|
|
686
|
+
type: 'dynamic-tool',
|
|
687
|
+
toolName: tr.toolName,
|
|
688
|
+
toolCallId: tr.toolCallId,
|
|
689
|
+
state: 'output-error',
|
|
690
|
+
input: tr.args,
|
|
691
|
+
errorText: tr.result.error ?? 'Tool execution failed',
|
|
692
|
+
});
|
|
693
|
+
}
|
|
628
694
|
}
|
|
629
695
|
const assistantMessage = {
|
|
630
696
|
id: generateMessageId(),
|
|
@@ -636,9 +702,9 @@ export class VercelAIAdapter extends BaseProtocolAdapter {
|
|
|
636
702
|
// 7. Clear batching state BEFORE the async sendMessage call
|
|
637
703
|
this.pendingToolCalls.clear();
|
|
638
704
|
this.collectedToolResults.clear();
|
|
705
|
+
this.deferredToolMeta.clear();
|
|
639
706
|
// 8. Update stored message history
|
|
640
707
|
this.messageHistory = continuationMessages;
|
|
641
|
-
console.log('[VercelAIAdapter] === CONTINUATION MESSAGES ===', continuationMessages.map((m, i) => `[${i}] role=${m.role} parts=${m.parts.length}`));
|
|
642
708
|
// 9. Mark as continuation
|
|
643
709
|
this.isContinuation = true;
|
|
644
710
|
// 10. Send ONE continuation request with all tool results
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import JSON5 from 'json5/dist/index.mjs';
|
|
6
|
+
export const parse = JSON5.parse.bind(JSON5);
|
|
7
|
+
export const stringify = JSON5.stringify.bind(JSON5);
|
|
8
|
+
export default JSON5;
|