@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
|
@@ -7,8 +7,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
8
8
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
9
9
|
import { Box } from '@datalayer/primer-addons';
|
|
10
|
+
import { ErrorView } from './components';
|
|
10
11
|
import { Button, Heading, SegmentedControl, Spinner, Text, } from '@primer/react';
|
|
11
|
-
import {
|
|
12
|
+
import { SignOutIcon, ToolsIcon } from '@primer/octicons-react';
|
|
12
13
|
import { useCoreStore } from '@datalayer/core';
|
|
13
14
|
import { DEFAULT_SERVICE_URLS } from '@datalayer/core/lib/api/constants';
|
|
14
15
|
import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel';
|
|
@@ -111,6 +112,8 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
111
112
|
const [toolApprovalState, setToolApprovalState] = useState({});
|
|
112
113
|
const [wsState, setWsState] = useState('closed');
|
|
113
114
|
const createdApprovalSignatures = useRef(new Set());
|
|
115
|
+
const toolRespondersRef = useRef(new Map());
|
|
116
|
+
const respondedToolCallsRef = useRef(new Set());
|
|
114
117
|
const resolveLocalRef = useRef(async () => null);
|
|
115
118
|
const authFetchRef = useRef((url, opts) => fetch(url, opts));
|
|
116
119
|
const chatAuthToken = token === null ? undefined : token;
|
|
@@ -126,6 +129,29 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
126
129
|
...(opts.headers ?? {}),
|
|
127
130
|
},
|
|
128
131
|
}), [token]);
|
|
132
|
+
const emitServerToolDecision = useCallback((toolName, toolArgs, approved, approvalId, message) => {
|
|
133
|
+
const signature = approvalSignature(toolName, toolArgs);
|
|
134
|
+
const responder = toolRespondersRef.current.get(signature);
|
|
135
|
+
if (!responder?.respond) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
if (respondedToolCallsRef.current.has(responder.toolCallId)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
setToolApprovalState(prev => ({
|
|
142
|
+
...prev,
|
|
143
|
+
[responder.toolCallId]: approved ? 'approved' : 'denied',
|
|
144
|
+
}));
|
|
145
|
+
respondedToolCallsRef.current.add(responder.toolCallId);
|
|
146
|
+
responder.respond({
|
|
147
|
+
type: 'tool-approval-decision',
|
|
148
|
+
approved,
|
|
149
|
+
approvalId,
|
|
150
|
+
toolName: responder.toolName || toolName,
|
|
151
|
+
...(message ? { message } : {}),
|
|
152
|
+
});
|
|
153
|
+
return true;
|
|
154
|
+
}, []);
|
|
129
155
|
useEffect(() => {
|
|
130
156
|
let isCancelled = false;
|
|
131
157
|
const createLocalAgent = async () => {
|
|
@@ -315,6 +341,8 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
315
341
|
const action = wsEvent === 'tool_approval_approved' ? 'approve' : 'reject';
|
|
316
342
|
void (async () => {
|
|
317
343
|
try {
|
|
344
|
+
const approved = wsEvent === 'tool_approval_approved';
|
|
345
|
+
emitServerToolDecision(approval.tool_name, approval.tool_args ?? {}, approved, approval.id, approval.note);
|
|
318
346
|
const localMatch = await resolveLocalRef.current(approval.tool_name, approval.tool_args ?? {});
|
|
319
347
|
if (localMatch) {
|
|
320
348
|
const localBaseUrl = `${agentBaseUrl}/api/v1/tool-approvals/${localMatch.id}/${action}`;
|
|
@@ -356,6 +384,7 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
356
384
|
chatAuthToken,
|
|
357
385
|
agentId,
|
|
358
386
|
pollApprovals,
|
|
387
|
+
emitServerToolDecision,
|
|
359
388
|
]);
|
|
360
389
|
// Keep refs in sync so the WS handler always has the latest functions.
|
|
361
390
|
useEffect(() => {
|
|
@@ -384,8 +413,9 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
384
413
|
throw new Error(errorText ||
|
|
385
414
|
`Failed to approve request (${response.status} ${response.statusText})`);
|
|
386
415
|
}
|
|
387
|
-
// In server mode
|
|
388
|
-
//
|
|
416
|
+
// In server mode, UI/continuation updates are websocket-driven only.
|
|
417
|
+
// The click only sends approve to the server; local chat reacts when
|
|
418
|
+
// tool_approval_approved is received.
|
|
389
419
|
if (mode !== 'server') {
|
|
390
420
|
setApprovals(prev => prev.filter(a => a.id !== requestId));
|
|
391
421
|
void pollApprovals();
|
|
@@ -402,7 +432,14 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
402
432
|
finally {
|
|
403
433
|
setApprovalLoading(null);
|
|
404
434
|
}
|
|
405
|
-
}, [
|
|
435
|
+
}, [
|
|
436
|
+
approvals,
|
|
437
|
+
mode,
|
|
438
|
+
aiAgentsBaseUrl,
|
|
439
|
+
agentBaseUrl,
|
|
440
|
+
authFetch,
|
|
441
|
+
pollApprovals,
|
|
442
|
+
]);
|
|
406
443
|
const reject = useCallback(async (requestId, note) => {
|
|
407
444
|
setApprovalLoading(requestId);
|
|
408
445
|
setApprovalError(null);
|
|
@@ -423,8 +460,9 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
423
460
|
throw new Error(errorText ||
|
|
424
461
|
`Failed to reject request (${response.status} ${response.statusText})`);
|
|
425
462
|
}
|
|
426
|
-
// In server mode
|
|
427
|
-
//
|
|
463
|
+
// In server mode, UI/continuation updates are websocket-driven only.
|
|
464
|
+
// The click only sends reject to the server; local chat reacts when
|
|
465
|
+
// tool_approval_rejected is received.
|
|
428
466
|
if (mode !== 'server') {
|
|
429
467
|
setApprovals(prev => prev.filter(a => a.id !== requestId));
|
|
430
468
|
void pollApprovals();
|
|
@@ -441,7 +479,14 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
441
479
|
finally {
|
|
442
480
|
setApprovalLoading(null);
|
|
443
481
|
}
|
|
444
|
-
}, [
|
|
482
|
+
}, [
|
|
483
|
+
approvals,
|
|
484
|
+
mode,
|
|
485
|
+
aiAgentsBaseUrl,
|
|
486
|
+
agentBaseUrl,
|
|
487
|
+
authFetch,
|
|
488
|
+
pollApprovals,
|
|
489
|
+
]);
|
|
445
490
|
const ensureServerApproval = useCallback(async (toolName, args) => {
|
|
446
491
|
if (mode !== 'server' || !aiAgentsBaseUrl || !isReady) {
|
|
447
492
|
return;
|
|
@@ -508,19 +553,46 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
508
553
|
return stableStringify(approval.tool_args ?? {}) === argsSig;
|
|
509
554
|
}) || null);
|
|
510
555
|
}, [approvals]);
|
|
511
|
-
const handleToolLevelApprove = useCallback(async (toolCallId, requestId) => {
|
|
556
|
+
const handleToolLevelApprove = useCallback(async (toolCallId, requestId, toolName, respond) => {
|
|
512
557
|
const ok = await approve(requestId, 'Approved from tool message card');
|
|
513
558
|
if (ok) {
|
|
514
|
-
|
|
559
|
+
if (mode !== 'server') {
|
|
560
|
+
setToolApprovalState(prev => ({ ...prev, [toolCallId]: 'approved' }));
|
|
561
|
+
respond?.({
|
|
562
|
+
type: 'tool-approval-decision',
|
|
563
|
+
approved: true,
|
|
564
|
+
approvalId: requestId,
|
|
565
|
+
toolName,
|
|
566
|
+
});
|
|
567
|
+
}
|
|
515
568
|
}
|
|
516
|
-
}, [approve]);
|
|
517
|
-
const handleToolLevelDeny = useCallback(async (toolCallId, requestId) => {
|
|
569
|
+
}, [approve, mode]);
|
|
570
|
+
const handleToolLevelDeny = useCallback(async (toolCallId, requestId, toolName, respond) => {
|
|
518
571
|
const ok = await reject(requestId, 'Rejected from tool message card');
|
|
519
572
|
if (ok) {
|
|
520
|
-
|
|
573
|
+
if (mode !== 'server') {
|
|
574
|
+
setToolApprovalState(prev => ({ ...prev, [toolCallId]: 'denied' }));
|
|
575
|
+
respond?.({
|
|
576
|
+
type: 'tool-approval-decision',
|
|
577
|
+
approved: false,
|
|
578
|
+
approvalId: requestId,
|
|
579
|
+
toolName,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}, [reject, mode]);
|
|
584
|
+
const renderToolResult = useCallback(({ toolCallId, toolName, args, result, status, error, respond }) => {
|
|
585
|
+
const signature = approvalSignature(toolName, args);
|
|
586
|
+
if (respond && status === 'inProgress') {
|
|
587
|
+
toolRespondersRef.current.set(signature, {
|
|
588
|
+
toolCallId,
|
|
589
|
+
toolName,
|
|
590
|
+
respond,
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
else if (status === 'complete' || status === 'error') {
|
|
594
|
+
toolRespondersRef.current.delete(signature);
|
|
521
595
|
}
|
|
522
|
-
}, [reject]);
|
|
523
|
-
const renderToolResult = useCallback(({ toolCallId, toolName, args, result, status, error }) => {
|
|
524
596
|
const matchedApproval = findMatchingApproval(toolName, args);
|
|
525
597
|
const resultObject = result && typeof result === 'object'
|
|
526
598
|
? result
|
|
@@ -539,9 +611,9 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
539
611
|
? 'pending'
|
|
540
612
|
: undefined);
|
|
541
613
|
return (_jsx(ToolCallDisplay, { toolCallId: toolCallId, toolName: toolName, args: args, result: result, status: status, error: error, approvalRequired: !!approvalState, approvalState: approvalState, approvalLoading: loadingThisApproval, onApprove: matchedApproval
|
|
542
|
-
? () => void handleToolLevelApprove(toolCallId, matchedApproval.id)
|
|
614
|
+
? () => void handleToolLevelApprove(toolCallId, matchedApproval.id, toolName, respond)
|
|
543
615
|
: undefined, onDeny: matchedApproval
|
|
544
|
-
? () => void handleToolLevelDeny(toolCallId, matchedApproval.id)
|
|
616
|
+
? () => void handleToolLevelDeny(toolCallId, matchedApproval.id, toolName, respond)
|
|
545
617
|
: undefined }));
|
|
546
618
|
}, [
|
|
547
619
|
mode,
|
|
@@ -563,14 +635,7 @@ const AgentToolApprovalsInner = ({ onLogout, }) => {
|
|
|
563
635
|
}, children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { color: 'fg.muted' }, children: "Launching tool approval demo..." })] }));
|
|
564
636
|
}
|
|
565
637
|
if (runtimeStatus === 'error' || hookError) {
|
|
566
|
-
return (
|
|
567
|
-
display: 'flex',
|
|
568
|
-
flexDirection: 'column',
|
|
569
|
-
alignItems: 'center',
|
|
570
|
-
justifyContent: 'center',
|
|
571
|
-
height: '100vh',
|
|
572
|
-
gap: 3,
|
|
573
|
-
}, children: [_jsx(AlertIcon, { size: 48 }), _jsx(Text, { sx: { color: 'danger.fg' }, children: hookError || 'Agent failed to start' })] }));
|
|
638
|
+
return _jsx(ErrorView, { error: hookError, onLogout: onLogout });
|
|
574
639
|
}
|
|
575
640
|
const serverPanel = mode === 'server' ? (_jsxs(Box, { sx: {
|
|
576
641
|
width: 320,
|