@datalayer/agent-runtimes 1.3.75 → 1.3.79
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/lib/agents/AgentDetails.d.ts +16 -2
- package/lib/agents/AgentDetails.js +381 -272
- package/lib/chat/ChatFloating.d.ts +12 -2
- package/lib/chat/ChatFloating.js +48 -11
- package/lib/chat/assistant/AgentDetailsDialog.d.ts +21 -0
- package/lib/chat/assistant/AgentDetailsDialog.js +19 -0
- package/lib/chat/assistant/AssistantStage.d.ts +51 -5
- package/lib/chat/assistant/AssistantStage.js +60 -10
- package/lib/chat/assistant/BalloonParts.d.ts +18 -4
- package/lib/chat/assistant/BalloonParts.js +46 -41
- package/lib/chat/assistant/BalloonVisual.js +2 -1
- package/lib/chat/assistant/SandboxDetailsDialog.d.ts +44 -0
- package/lib/chat/assistant/SandboxDetailsDialog.js +214 -0
- package/lib/chat/assistant/SpeechBalloon.d.ts +8 -6
- package/lib/chat/assistant/SpeechBalloon.js +29 -30
- package/lib/chat/assistant/assistantDetails.d.ts +84 -0
- package/lib/chat/assistant/assistantDetails.js +140 -0
- package/lib/chat/assistant/formats/files.d.ts +23 -0
- package/lib/chat/assistant/formats/files.js +48 -0
- package/lib/chat/assistant/formats/index.d.ts +2 -0
- package/lib/chat/assistant/formats/index.js +1 -0
- package/lib/chat/assistant/state.d.ts +7 -14
- package/lib/chat/assistant/state.js +21 -20
- package/lib/chat/assistant/toolLine.d.ts +16 -0
- package/lib/chat/assistant/toolLine.js +46 -0
- package/lib/chat/base/ChatBase.js +20 -0
- package/lib/chat/base/loopMessage.d.ts +37 -0
- package/lib/chat/base/loopMessage.js +37 -0
- package/lib/chat/messages/ChatMarkdown.d.ts +16 -0
- package/lib/chat/messages/ChatMarkdown.js +18 -0
- package/lib/chat/messages/ChatMessageList.d.ts +8 -1
- package/lib/chat/messages/ChatMessageList.js +24 -18
- package/lib/chat/styles/streamdownStyles.js +3 -1
- package/lib/chat/tools/ToolCallDisplay.d.ts +8 -1
- package/lib/chat/tools/ToolCallDisplay.js +8 -7
- package/lib/components/code-sandboxes/CodeSandboxCellVariablesDialog.js +5 -11
- package/lib/components/code-sandboxes/CodeSandboxVariables.d.ts +8 -0
- package/lib/components/code-sandboxes/CodeSandboxVariables.js +17 -11
- package/lib/components/teams/A2ATeamGraph.d.ts +30 -3
- package/lib/components/teams/A2ATeamGraph.js +264 -41
- package/lib/components/teams/TeamNotebookView.js +15 -0
- package/lib/components/teams/teamNotebookKernel.d.ts +3 -0
- package/lib/components/teams/teamNotebookKernel.js +17 -0
- package/lib/components/teams/useA2ATeam.d.ts +10 -6
- package/lib/components/teams/useA2ATeam.js +29 -8
- package/lib/examples/AgentA2ATeamExample.js +6 -0
- package/lib/examples/AssistantExample.js +3 -24
- package/lib/examples/AssistantGalleryExample.js +2 -1
- package/lib/examples/exampleGroups.d.ts +1 -1
- package/lib/examples/exampleGroups.js +1 -1
- package/lib/examples/utils/assistantGallery.d.ts +7 -6
- package/lib/examples/utils/assistantGallery.js +23 -8
- package/lib/jupyter/exec/Python.d.ts +0 -1
- package/lib/jupyter/exec/Python.js +0 -32
- package/lib/jupyter/exec/Snippets.d.ts +4 -12
- package/lib/jupyter/exec/Snippets.js +0 -8
- package/lib/loop/apps/AppFeedback.js +3 -1
- package/lib/loop/apps/AppKept.d.ts +22 -0
- package/lib/loop/apps/AppKept.js +36 -0
- package/lib/loop/apps/AppRenderer.d.ts +11 -1
- package/lib/loop/apps/AppRenderer.js +21 -3
- package/lib/loop/apps/checks.d.ts +7 -0
- package/lib/loop/apps/checks.js +39 -0
- package/lib/loop/apps/index.d.ts +3 -0
- package/lib/loop/apps/index.js +3 -0
- package/lib/loop/apps/kept.d.ts +30 -0
- package/lib/loop/apps/kept.js +52 -0
- package/lib/loop/apps/records.d.ts +12 -4
- package/lib/loop/apps/records.js +13 -5
- package/lib/loop/apps/saved.d.ts +30 -0
- package/lib/loop/apps/saved.js +40 -0
- package/lib/loop/embed/AppEmbed.d.ts +8 -1
- package/lib/loop/embed/AppEmbed.js +4 -4
- package/lib/loop/embed/LoopEmbed.d.ts +6 -1
- package/lib/loop/embed/LoopEmbed.js +4 -2
- package/lib/loop/embed/element.js +1 -1
- package/lib/loop/plugins/agents/DatalayerAgentBridge.js +12 -6
- package/lib/loop/plugins/agents/browserService.d.ts +7 -1
- package/lib/loop/plugins/agents/browserService.js +4 -0
- package/lib/loop/plugins/agents/plugin.d.ts +16 -0
- package/lib/loop/plugins/agents/switchable.d.ts +3 -0
- package/lib/loop/plugins/agents/switchable.js +1 -0
- package/lib/loop/plugins/app-activity/index.js +3 -0
- package/lib/loop/plugins/app-computer/index.js +3 -0
- package/lib/loop/plugins/app-rules/AppRulesCard.d.ts +5 -0
- package/lib/loop/plugins/app-rules/AppRulesCard.js +25 -6
- package/lib/loop/plugins/app-rules/index.js +3 -0
- package/lib/loop/plugins/assistant/index.d.ts +7 -2
- package/lib/loop/plugins/assistant/index.js +53 -4
- package/lib/loop/plugins/assistant-characters/index.d.ts +7 -0
- package/lib/loop/plugins/assistant-characters/index.js +17 -0
- package/lib/loop/plugins/chat/ChatView.js +4 -1
- package/lib/loop/plugins/page-layout/SplitLayout.d.ts +2 -1
- package/lib/loop/plugins/page-layout/SplitLayout.js +4 -0
- package/lib/loop/presets.d.ts +4 -0
- package/lib/loop/presets.js +3 -1
- package/lib/loop/shell/LoopWorkspace.d.ts +7 -0
- package/lib/loop/shell/LoopWorkspace.js +5 -4
- package/lib/loop/shell/SidebarRail.d.ts +53 -0
- package/lib/loop/shell/SidebarRail.js +74 -0
- package/lib/loop/shell/index.d.ts +2 -0
- package/lib/loop/shell/index.js +2 -0
- package/lib/loop/shell/paneMotion.d.ts +21 -0
- package/lib/loop/shell/paneMotion.js +37 -0
- package/lib/specs/apps.js +8 -5
- package/lib/specs/uiPlugins.js +529 -0
- package/lib/types/agentspecs.d.ts +5 -3
- package/lib/types/chat.d.ts +5 -0
- package/package.json +2 -2
- package/scripts/codegen/generate_ui_plugins.py +112 -2
|
@@ -26,6 +26,7 @@ import { type PresenceState } from './presence/presenceStatus';
|
|
|
26
26
|
import type { AgentInspectorSink } from '../components/inspector/agentInspector';
|
|
27
27
|
import type { AssistantMenuItem } from './assistant/AssistantContextMenu';
|
|
28
28
|
import type { AssistantAbout } from './assistant/AssistantStage';
|
|
29
|
+
import { type AssistantSandbox } from './assistant/assistantDetails';
|
|
29
30
|
import type { ChatCommonProps, ChatViewMode, ThemeOverrides } from '../types';
|
|
30
31
|
/**
|
|
31
32
|
* A conversation the host draws in the floating window, in place of the
|
|
@@ -184,8 +185,17 @@ export interface ChatFloatingProps extends ChatCommonProps {
|
|
|
184
185
|
onBalloonDisplayChange?: (display: BalloonDisplay) => void;
|
|
185
186
|
/** Opens the host's character picker, from the assistant's menu. */
|
|
186
187
|
onChangeCharacter?: () => void;
|
|
187
|
-
/**
|
|
188
|
+
/**
|
|
189
|
+
* What the assistant's menu's *About* and *Agent Details…* say. The
|
|
190
|
+
* chat's own agent (its id and runtime, from `endpoint`) is described
|
|
191
|
+
* without it.
|
|
192
|
+
*/
|
|
188
193
|
about?: AssistantAbout;
|
|
194
|
+
/**
|
|
195
|
+
* The agent's code sandbox, for *Code Sandbox Details…*. Without it, the
|
|
196
|
+
* sandbox the agent's runtime reports (its codemode status), if any.
|
|
197
|
+
*/
|
|
198
|
+
sandbox?: AssistantSandbox;
|
|
189
199
|
/** The host's own entries of the assistant's menu. */
|
|
190
200
|
contextMenu?: readonly AssistantMenuItem[];
|
|
191
201
|
/**
|
|
@@ -200,5 +210,5 @@ export interface ChatFloatingProps extends ChatCommonProps {
|
|
|
200
210
|
* ChatFloating component
|
|
201
211
|
* A floating chat window built on ChatBase
|
|
202
212
|
*/
|
|
203
|
-
export declare function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode, title, description, position, defaultOpen, width, height, showHeader, showButton, showNewChatButton, showClearButton, showSettingsButton, enableKeyboardShortcuts, toggleShortcut, showPoweredBy, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose, escapeToClose, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip, brandColor, buttonGlow, offset, animationDuration, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick, hideMessagesAfterToolUI, defaultViewMode, onViewModeChange, sidebarMountPoint, showPanelBackdrop, availableModels, showModelSelector, showToolsMenu, showSkillsMenu, showTokenUsage, showContextRing, themeVariant, themeOverrides, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching, launchingMessage, assistantCharacter, balloonDisplay: balloonDisplayGiven, expandTarget, conversation, decisions, voice, inspector, onBalloonDisplayChange, onChangeCharacter, about, contextMenu, }: ChatFloatingProps): React.JSX.Element;
|
|
213
|
+
export declare function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode, title, description, position, defaultOpen, width, height, showHeader, showButton, showNewChatButton, showClearButton, showSettingsButton, enableKeyboardShortcuts, toggleShortcut, showPoweredBy, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose, escapeToClose, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip, brandColor, buttonGlow, offset, animationDuration, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick, hideMessagesAfterToolUI, defaultViewMode, onViewModeChange, sidebarMountPoint, showPanelBackdrop, availableModels, showModelSelector, showToolsMenu, showSkillsMenu, showTokenUsage, showContextRing, themeVariant, themeOverrides, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching, launchingMessage, assistantCharacter, balloonDisplay: balloonDisplayGiven, expandTarget, conversation, decisions, voice, inspector, onBalloonDisplayChange, onChangeCharacter, about, sandbox, contextMenu, }: ChatFloatingProps): React.JSX.Element;
|
|
204
214
|
export default ChatFloating;
|
package/lib/chat/ChatFloating.js
CHANGED
|
@@ -40,10 +40,12 @@ import { ConversationBalloonHeader, CurrentBalloonBody, } from './assistant/Ball
|
|
|
40
40
|
import { DEFAULT_BALLOON_DISPLAY, conversationCount, newestToolLine, toolLineText, } from './assistant/toolLine';
|
|
41
41
|
import { SpeechBalloon } from './assistant/SpeechBalloon';
|
|
42
42
|
import { DEFAULT_ASSISTANT_CHARACTER, } from './assistant/characters';
|
|
43
|
-
import { assistantStateOf,
|
|
43
|
+
import { assistantStateOf, latestSaying, newestIsAnswer, keepAway, keptAway, ASSISTANT_WORDS, } from './assistant/state';
|
|
44
44
|
import { presenceState, presenceToolOf, } from './presence/presenceStatus';
|
|
45
45
|
import { useChatOpen, useChatMessages, useChatStore, } from '../stores/chatStore';
|
|
46
46
|
import { useChatKeyboardShortcuts, getShortcutDisplay, } from '@datalayer/core/lib/hooks';
|
|
47
|
+
import { assistantSandboxOf, } from './assistant/assistantDetails';
|
|
48
|
+
import { useAgentRuntimeCodemodeStatus } from '../stores/agentRuntimeStore';
|
|
47
49
|
/**
|
|
48
50
|
* Hook to detect mobile viewport
|
|
49
51
|
*/
|
|
@@ -70,7 +72,7 @@ const clamp = (value, max) => Math.max(8, Math.min(value, Math.max(8, max)));
|
|
|
70
72
|
* ChatFloating component
|
|
71
73
|
* A floating chat window built on ChatBase
|
|
72
74
|
*/
|
|
73
|
-
export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode = true, title = 'Chat', description = 'Start a conversation with the AI agent.', position = 'bottom-right', defaultOpen = false, width = 400, height = 550, showHeader = true, showButton = true, showNewChatButton = true, showClearButton = true, showSettingsButton = false, enableKeyboardShortcuts = true, toggleShortcut = '/', showPoweredBy = true, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose = false, escapeToClose = true, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip = 'Chat with AI', brandColor, buttonGlow = true, offset = 20, animationDuration = 200, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, defaultViewMode = 'floating', onViewModeChange, sidebarMountPoint = null, showPanelBackdrop = false, availableModels, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, showTokenUsage = true, showContextRing = false, themeVariant, themeOverrides, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation = false, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching = false, launchingMessage, assistantCharacter = DEFAULT_ASSISTANT_CHARACTER, balloonDisplay: balloonDisplayGiven = DEFAULT_BALLOON_DISPLAY, expandTarget, conversation, decisions, voice, inspector, onBalloonDisplayChange, onChangeCharacter, about, contextMenu, }) {
|
|
75
|
+
export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useStoreMode = true, title = 'Chat', description = 'Start a conversation with the AI agent.', position = 'bottom-right', defaultOpen = false, width = 400, height = 550, showHeader = true, showButton = true, showNewChatButton = true, showClearButton = true, showSettingsButton = false, enableKeyboardShortcuts = true, toggleShortcut = '/', showPoweredBy = true, promptVariant, mentionableAgents, poweredByProps, clickOutsideToClose = false, escapeToClose = true, className, onSettingsClick, onNewChat, onOpen, onClose, onStateUpdate, children, brandIcon, buttonIcon, buttonTooltip = 'Chat with AI', brandColor, buttonGlow = true, offset = 20, animationDuration = 200, renderToolResult, frontendTools, initialState: _initialState, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, defaultViewMode = 'floating', onViewModeChange, sidebarMountPoint = null, showPanelBackdrop = false, availableModels, showModelSelector = false, showToolsMenu = false, showSkillsMenu = false, showTokenUsage = true, showContextRing = false, themeVariant, themeOverrides, colorMode, runtimeId, historyEndpoint, authToken, historyAuthToken, pendingPrompt, showInformation = false, onInformationClick, onToolCallStart, onToolCallComplete, showToolApprovalBanner, pendingApprovals, onApproveApproval, onRejectApproval, panelProps, launching = false, launchingMessage, assistantCharacter = DEFAULT_ASSISTANT_CHARACTER, balloonDisplay: balloonDisplayGiven = DEFAULT_BALLOON_DISPLAY, expandTarget, conversation, decisions, voice, inspector, onBalloonDisplayChange, onChangeCharacter, about, sandbox, contextMenu, }) {
|
|
74
76
|
// The chat's own send, once it can: what a suggestion in the balloon sends.
|
|
75
77
|
const chatControls = useRef(null);
|
|
76
78
|
const [suggestionPrompt, setSuggestionPrompt] = useState();
|
|
@@ -150,6 +152,8 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
150
152
|
const [ownTool, setOwnTool] = useState();
|
|
151
153
|
const [messageCount, setMessageCount] = useState(0);
|
|
152
154
|
// The conversation's messages, listed in the closed `history` balloon.
|
|
155
|
+
// The chat's own items — its messages and tool calls — as it holds them:
|
|
156
|
+
// the balloon draws them with the chat's components.
|
|
153
157
|
const [ownHistory, setOwnHistory] = useState([]);
|
|
154
158
|
/*
|
|
155
159
|
* Its voice (VOICE.md V1): the answers said by the speech service, as
|
|
@@ -273,7 +277,16 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
273
277
|
// The tool line, while its call runs or its turn goes on (T-23).
|
|
274
278
|
const toolSaid = toolLine && (toolLine.phase === 'running' || atWork) ? toolLine : undefined;
|
|
275
279
|
// Current: what is said now — thinking until the answer's words arrive.
|
|
276
|
-
|
|
280
|
+
// The words as written (markdown, drawn by the chat's markdown), or cut
|
|
281
|
+
// to fit with the whole kept for *more*.
|
|
282
|
+
const currentWords = atWork && !answering
|
|
283
|
+
? 'Thinking…'
|
|
284
|
+
: (saying?.more ? saying.text : saying?.markdown) || undefined;
|
|
285
|
+
const currentWhole = atWork && !answering
|
|
286
|
+
? undefined
|
|
287
|
+
: saying?.more
|
|
288
|
+
? saying.markdown
|
|
289
|
+
: undefined;
|
|
277
290
|
// History: the closed balloon lists the conversation, not its newest line.
|
|
278
291
|
const listedHistory = !showsCurrent && !conversation && ownHistory.length > 0
|
|
279
292
|
? ownHistory
|
|
@@ -303,6 +316,7 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
303
316
|
? // Current: the words as they are written, whole.
|
|
304
317
|
{
|
|
305
318
|
text: currentWords ?? description,
|
|
319
|
+
fullText: currentWhole,
|
|
306
320
|
more: saying?.more,
|
|
307
321
|
speaking: answering && atWork,
|
|
308
322
|
busy: atWork,
|
|
@@ -371,12 +385,7 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
371
385
|
? previous
|
|
372
386
|
: line);
|
|
373
387
|
setMessageCount(conversationCount(items));
|
|
374
|
-
|
|
375
|
-
setOwnHistory(previous => previous.length === listed.length &&
|
|
376
|
-
previous.every((message, index) => message.id === listed[index].id &&
|
|
377
|
-
message.text === listed[index].text)
|
|
378
|
-
? previous
|
|
379
|
-
: listed);
|
|
388
|
+
setOwnHistory(items);
|
|
380
389
|
setVoiceItems(items);
|
|
381
390
|
const said = latestSaying(items);
|
|
382
391
|
setSaying(previous => previous?.id === said?.id && previous?.text === said?.text
|
|
@@ -540,6 +549,34 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
540
549
|
showSkillsMenu,
|
|
541
550
|
showTokenUsage,
|
|
542
551
|
]);
|
|
552
|
+
// What the assistant's menu says of the agent (*Agent Details…*): the
|
|
553
|
+
// host's words first, the chat's own agent and runtime under them.
|
|
554
|
+
const runtimeBase = endpoint?.match(/^(.*?)\/api\/v1\//)?.[1];
|
|
555
|
+
const agentAbout = useMemo(() => about || protocol?.agentId
|
|
556
|
+
? {
|
|
557
|
+
name: title,
|
|
558
|
+
protocol: protocol?.type,
|
|
559
|
+
url: protocol?.endpoint,
|
|
560
|
+
agentId: protocol?.agentId,
|
|
561
|
+
apiBase: runtimeBase,
|
|
562
|
+
...about,
|
|
563
|
+
}
|
|
564
|
+
: undefined, [about, protocol, title, runtimeBase]);
|
|
565
|
+
// Its sandbox (*Code Sandbox Details…*): the host's, or what its runtime
|
|
566
|
+
// reports.
|
|
567
|
+
const codemodeStatus = useAgentRuntimeCodemodeStatus();
|
|
568
|
+
const agentSandbox = useMemo(() => sandbox ??
|
|
569
|
+
assistantSandboxOf(codemodeStatus
|
|
570
|
+
?.sandbox, { agentId: protocol?.agentId, serverUrl: runtimeBase }) ??
|
|
571
|
+
// An agent on a runtime can always have one: offered before it runs.
|
|
572
|
+
(protocol?.agentId && runtimeBase
|
|
573
|
+
? {
|
|
574
|
+
kind: 'runtime',
|
|
575
|
+
status: 'not running',
|
|
576
|
+
agentId: protocol.agentId,
|
|
577
|
+
serverUrl: runtimeBase,
|
|
578
|
+
}
|
|
579
|
+
: undefined), [sandbox, codemodeStatus, protocol?.agentId, runtimeBase]);
|
|
543
580
|
// Clear messages when endpoint/protocol changes (e.g., switching examples)
|
|
544
581
|
useEffect(() => {
|
|
545
582
|
clearStoreMessages();
|
|
@@ -1058,7 +1095,7 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
1058
1095
|
showAvatars: true,
|
|
1059
1096
|
}, placeholder: "Type a message...", backgroundColor: "canvas.subtle", frontendTools: frontendTools, showModelSelector: showModelSelector, availableModels: availableModels, showToolsMenu: showToolsMenu, showSkillsMenu: showSkillsMenu, showTokenUsage: showTokenUsage, showContextRing: showContextRing, runtimeId: runtimeId, historyEndpoint: historyEndpoint, historyAuthToken: historyAuthToken, pendingPrompt: pendingPrompt ?? suggestionPrompt, inspector: inspector, showInformation: showInformation, onInformationClick: onInformationClick, onToolCallStart: onToolCallStart, onToolCallComplete: onToolCallComplete, showToolApprovalBanner: showToolApprovalBanner, pendingApprovals: pendingApprovals, onApproveApproval: onApproveApproval, onRejectApproval: onRejectApproval, voice: voice, voiceSpeaking: speakerState.speaking, onStopSpeaking: speaker ? stopSpeaking : undefined, ...panelProps, ...assistantChat, onLoadingChange: handleLoadingChange, onDisplayItemsChange: handleDisplayItemsChange, onSendReady: handleSendReady, children: conversationBalloon && currentOpen ? (
|
|
1060
1097
|
// Current: the one thing said or done now, over the composer.
|
|
1061
|
-
_jsx(Box, { sx: { px: 3, pt: 3, pb: 2, overflow: 'hidden' }, children: _jsx(CurrentBalloonBody, { text: toolSaid ? undefined : (currentWords ?? description), tool: toolSaid, busy: atWork, speaking: answering && atWork, waiting: atWork && !answering }) })) : (children) }))] }));
|
|
1098
|
+
_jsx(Box, { sx: { px: 3, pt: 3, pb: 2, overflow: 'hidden' }, children: _jsx(CurrentBalloonBody, { text: toolSaid ? undefined : (currentWords ?? description), fullText: toolSaid ? undefined : currentWhole, tool: toolSaid, busy: atWork, speaking: answering && atWork, waiting: atWork && !answering }) })) : (children) }))] }));
|
|
1062
1099
|
/*
|
|
1063
1100
|
* The floating popup's button. Words not yet heard make it blink for the
|
|
1064
1101
|
* person's attention, until the chat is opened; hovered, they show in a
|
|
@@ -1118,7 +1155,7 @@ export function ChatFloating({ endpoint, protocol: protocolProp, useStore: useSt
|
|
|
1118
1155
|
setSpeechMuted(!speechMuted);
|
|
1119
1156
|
},
|
|
1120
1157
|
}
|
|
1121
|
-
: undefined, onResetPosition: stageDrag.position ? stageDrag.reset : undefined, about:
|
|
1158
|
+
: undefined, onResetPosition: stageDrag.position ? stageDrag.reset : undefined, about: agentAbout, sandbox: agentSandbox, contextMenu: contextMenu })), showButton && !isOpen && !assistantShown && (_jsx(Box, { sx: {
|
|
1122
1159
|
...getPositionStyles(),
|
|
1123
1160
|
}, children: _jsxs(Box, { sx: {
|
|
1124
1161
|
position: 'relative',
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* *Agent Details…*, from the assistant's menu: the agent's `AgentDetails`
|
|
3
|
+
* in a dialog over the page. On an agent-runtimes server it reads what that
|
|
4
|
+
* server says of the agent (its spec, MCP servers, codemode, context); an
|
|
5
|
+
* agent in the page, or a peer known by its A2A card, is described by what
|
|
6
|
+
* its host knows: its Appspec, model and where it runs.
|
|
7
|
+
*
|
|
8
|
+
* Loaded when it is first opened, never with the character.
|
|
9
|
+
*
|
|
10
|
+
* @module chat/assistant/AgentDetailsDialog
|
|
11
|
+
*/
|
|
12
|
+
import type { JSX } from 'react';
|
|
13
|
+
import type { AssistantAbout } from './AssistantStage';
|
|
14
|
+
export type AgentDetailsDialogProps = {
|
|
15
|
+
about: AssistantAbout;
|
|
16
|
+
/** The character's name, when the agent has none of its own. */
|
|
17
|
+
name: string;
|
|
18
|
+
onClose: () => void;
|
|
19
|
+
};
|
|
20
|
+
export declare function AgentDetailsDialog({ about, name, onClose, }: AgentDetailsDialogProps): JSX.Element;
|
|
21
|
+
export default AgentDetailsDialog;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { Dialog } from '@primer/react';
|
|
4
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
5
|
+
import { AgentDetails } from '../../agents/AgentDetails';
|
|
6
|
+
export function AgentDetailsDialog({ about, name, onClose, }) {
|
|
7
|
+
// AgentDetails reads the runtime through react-query; a page that shows
|
|
8
|
+
// only a character has no client of its own.
|
|
9
|
+
const queries = useMemo(() => new QueryClient(), []);
|
|
10
|
+
const onRuntime = Boolean(about.agentId && about.apiBase);
|
|
11
|
+
return (_jsx(Dialog, { title: `${about.name ?? name} · Agent Details`, onClose: onClose, width: "xlarge", height: "large", children: _jsx("div", { "data-assistant-agent-details": "", children: _jsx(QueryClientProvider, { client: queries, children: _jsx(AgentDetails, { name: about.name ?? name, protocol: about.protocol ?? (onRuntime ? 'agent-runtimes' : 'browser'), url: about.url ?? '', messageCount: 0, agentId: about.agentId, apiBase: about.apiBase, onBack: onClose, showBackHeader: false, showUsage: onRuntime, padded: false, runtime: onRuntime, summary: {
|
|
12
|
+
spec: about.spec,
|
|
13
|
+
model: about.model,
|
|
14
|
+
where: about.where,
|
|
15
|
+
description: about.description,
|
|
16
|
+
skills: about.skills,
|
|
17
|
+
} }) }) }) }));
|
|
18
|
+
}
|
|
19
|
+
export default AgentDetailsDialog;
|
|
@@ -30,11 +30,13 @@ import { type AssistantCharacter } from './characters';
|
|
|
30
30
|
import { type BalloonSuggestion } from './SpeechBalloon';
|
|
31
31
|
import { type AssistantMenuItem } from './AssistantContextMenu';
|
|
32
32
|
import type { AgentInspectorSink } from '../../components/inspector/agentInspector';
|
|
33
|
+
import type { AssistantSandbox } from './assistantDetails';
|
|
33
34
|
import { type BalloonExpandTarget, type BalloonVisual } from './BalloonVisual';
|
|
34
35
|
import type { AssistantCharacterData } from './formats/types';
|
|
35
36
|
import type { DecisionAsker } from './decisions';
|
|
36
|
-
import type
|
|
37
|
-
import
|
|
37
|
+
import { type BalloonDisplay, type BalloonToolLine } from './toolLine';
|
|
38
|
+
import type { DisplayItem } from '../../types/chat';
|
|
39
|
+
import { type AssistantAway, type AssistantState, type BalloonApproval } from './state';
|
|
38
40
|
/** What the assistant's *About* says. */
|
|
39
41
|
export type AssistantAbout = {
|
|
40
42
|
/** The agent's name, or its application's. */
|
|
@@ -45,6 +47,19 @@ export type AssistantAbout = {
|
|
|
45
47
|
model?: string;
|
|
46
48
|
/** Where it runs: `in your browser`, `on a runtime`. */
|
|
47
49
|
where?: string;
|
|
50
|
+
/** What it does, in a sentence: its card's or its spec's description. */
|
|
51
|
+
description?: string;
|
|
52
|
+
/** What it can do: its card's skills. */
|
|
53
|
+
skills?: string[];
|
|
54
|
+
/**
|
|
55
|
+
* The agent on an agent-runtimes server, and that server: *Agent
|
|
56
|
+
* Details…* then reads its spec, MCP servers and codemode there.
|
|
57
|
+
*/
|
|
58
|
+
agentId?: string;
|
|
59
|
+
apiBase?: string;
|
|
60
|
+
/** How it is reached (`a2a`, `ag-ui`, …) and where. */
|
|
61
|
+
protocol?: string;
|
|
62
|
+
url?: string;
|
|
48
63
|
};
|
|
49
64
|
/**
|
|
50
65
|
* The entries of the assistant's menu, composed from what the host passes:
|
|
@@ -58,6 +73,10 @@ export declare function assistantMenuItems(options: {
|
|
|
58
73
|
/** The conversation entry's label; `false` leaves it out. */
|
|
59
74
|
conversationLabel?: string | false;
|
|
60
75
|
inspect?: () => void;
|
|
76
|
+
/** Opens *Agent Details…*: offered where the host describes the agent. */
|
|
77
|
+
agentDetails?: () => void;
|
|
78
|
+
/** Opens *Code Sandbox Details…*: offered where the agent has a sandbox. */
|
|
79
|
+
sandboxDetails?: () => void;
|
|
61
80
|
balloonDisplay?: BalloonDisplay;
|
|
62
81
|
onBalloonDisplayChange?: (display: BalloonDisplay) => void;
|
|
63
82
|
suggestions?: readonly BalloonSuggestion[];
|
|
@@ -123,6 +142,17 @@ export interface AssistantStageProps {
|
|
|
123
142
|
open: boolean;
|
|
124
143
|
/** Open or close the conversation. */
|
|
125
144
|
onToggle: () => void;
|
|
145
|
+
/**
|
|
146
|
+
* What a click on the character does, when it is not `onToggle`: a team's
|
|
147
|
+
* member shows and hides its balloon, and its menu's conversation entry
|
|
148
|
+
* (*Ask Sales*) still does `onToggle`.
|
|
149
|
+
*/
|
|
150
|
+
onCharacterClick?: () => void;
|
|
151
|
+
/**
|
|
152
|
+
* A key pressed on the focused character, after its own (the menu's):
|
|
153
|
+
* a team's member moves with the arrow keys.
|
|
154
|
+
*/
|
|
155
|
+
onCharacterKeyDown?: (event: React.KeyboardEvent<HTMLElement>) => void;
|
|
126
156
|
/**
|
|
127
157
|
* The peek while the conversation is closed: one short line — the agent's
|
|
128
158
|
* newest words, as the Office Assistant said them (T-23), or a welcome —
|
|
@@ -149,7 +179,7 @@ export interface AssistantStageProps {
|
|
|
149
179
|
* The conversation's messages (`history`): the balloon lists them all,
|
|
150
180
|
* counted and scrolled, rather than the newest line alone.
|
|
151
181
|
*/
|
|
152
|
-
history?: readonly
|
|
182
|
+
history?: readonly DisplayItem[];
|
|
153
183
|
/**
|
|
154
184
|
* The large visual `attachment` is the compact form of (a notebook):
|
|
155
185
|
* the balloon offers *Expand*, and draws it large — into
|
|
@@ -211,8 +241,13 @@ export interface AssistantStageProps {
|
|
|
211
241
|
};
|
|
212
242
|
/** Puts it back where it started, after a drag: offered in its menu. */
|
|
213
243
|
onResetPosition?: () => void;
|
|
214
|
-
/** What its menu's *About*
|
|
244
|
+
/** What its menu's *About* and *Agent Details…* say. */
|
|
215
245
|
about?: AssistantAbout;
|
|
246
|
+
/**
|
|
247
|
+
* The agent's code sandbox, when it has one: its menu offers *Code
|
|
248
|
+
* Sandbox Details…* — where it runs, and its variables.
|
|
249
|
+
*/
|
|
250
|
+
sandbox?: AssistantSandbox;
|
|
216
251
|
/** The host's or a plugin's own entries of its menu. */
|
|
217
252
|
contextMenu?: readonly AssistantMenuItem[];
|
|
218
253
|
/** Send it away (T-27): for the page, for the session, or for good. */
|
|
@@ -239,6 +274,17 @@ export interface AssistantStageProps {
|
|
|
239
274
|
* and its neighbours, not a page somebody is working on.
|
|
240
275
|
*/
|
|
241
276
|
stayPut?: boolean;
|
|
277
|
+
/**
|
|
278
|
+
* The agent's own name, used in place of the character's by its menu and
|
|
279
|
+
* its *Send … away*: `Sales`, where the character is a paper clip.
|
|
280
|
+
*/
|
|
281
|
+
agentName?: string;
|
|
282
|
+
/**
|
|
283
|
+
* The figure's accessible name, in place of *Talk to <character>*:
|
|
284
|
+
* `Sales (in your browser)`. Given this or `agentName`, the character's
|
|
285
|
+
* name describes the figure instead (`aria-describedby`).
|
|
286
|
+
*/
|
|
287
|
+
label?: string;
|
|
242
288
|
}
|
|
243
289
|
/** The openings of the mouth, by level: shut, a little, half, wide. */
|
|
244
290
|
export declare function mouthOpening(level: number): 0 | 1 | 2 | 3;
|
|
@@ -247,5 +293,5 @@ export declare function mouthOpening(level: number): 0 | 1 | 2 | 3;
|
|
|
247
293
|
* `data-assistant-mouth`, each frame, without drawing the character again.
|
|
248
294
|
*/
|
|
249
295
|
export declare function useMouth(stageRef: RefObject<HTMLElement | null>, mouthLevel: (() => number) | undefined, speaking: boolean): void;
|
|
250
|
-
export declare function AssistantStage({ character, state, size, place, stageRef, onDragStart, open, onToggle, balloon, insist, onDismiss, ownRef, decide, mouthLevel, stayPut, balloonDisplay, expandTarget, expandOnArrival, suggestions, onSuggestion, inspector, inspectAgent, conversationLabel, onBalloonDisplayChange, onStop, onNewChat, onClear, onChangeCharacter, speech, onResetPosition, about, contextMenu, }: AssistantStageProps): JSX.Element;
|
|
296
|
+
export declare function AssistantStage({ character, state, size, place, stageRef, onDragStart, open, onToggle, onCharacterClick, onCharacterKeyDown, balloon, insist, onDismiss, ownRef, decide, mouthLevel, stayPut, balloonDisplay, expandTarget, expandOnArrival, suggestions, onSuggestion, inspector, inspectAgent, conversationLabel, onBalloonDisplayChange, onStop, onNewChat, onClear, onChangeCharacter, speech, onResetPosition, about, sandbox, contextMenu, agentName, label, }: AssistantStageProps): JSX.Element;
|
|
251
297
|
export default AssistantStage;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Suspense, lazy, useCallback, useEffect, useRef, useState, } from 'react';
|
|
2
|
+
import { Suspense, lazy, useCallback, useEffect, useId, useRef, useState, } from 'react';
|
|
3
3
|
import { ActionList, ActionMenu, IconButton, useTheme } from '@primer/react';
|
|
4
4
|
import { Box } from '@datalayer/primer-addons';
|
|
5
|
-
import { CommentDiscussionIcon, InfoIcon, MuteIcon, PencilIcon, PlusIcon, PulseIcon, ScreenNormalIcon, SquareFillIcon, TrashIcon, UnmuteIcon, XIcon, } from '@primer/octicons-react';
|
|
5
|
+
import { CodeIcon, CommentDiscussionIcon, DependabotIcon, InfoIcon, MuteIcon, PencilIcon, PlusIcon, PulseIcon, ScreenNormalIcon, SquareFillIcon, TrashIcon, UnmuteIcon, XIcon, } from '@primer/octicons-react';
|
|
6
6
|
import { Dialog, Text } from '@primer/react';
|
|
7
7
|
import { assistantCharacter } from './characters';
|
|
8
8
|
import { BalloonHistoryLarge, SpeechBalloon, } from './SpeechBalloon';
|
|
@@ -10,6 +10,7 @@ import { conversationHeaderText } from './BalloonParts';
|
|
|
10
10
|
import { AssistantContextMenu, LONG_PRESS_MS, opensContextMenu, } from './AssistantContextMenu';
|
|
11
11
|
import { BalloonExpandContext, ExpandedVisual, focusExpanded, } from './BalloonVisual';
|
|
12
12
|
import { SpriteCharacter } from './SpriteCharacter';
|
|
13
|
+
import { conversationCount, } from './toolLine';
|
|
13
14
|
import { ASSISTANT_OBSTACLES, POINTER_CALM_MS, boxesMeet, pointerNear, } from './state';
|
|
14
15
|
/** The motions, by the state the stage is in. */
|
|
15
16
|
const MOTIONS = {
|
|
@@ -63,6 +64,10 @@ const AWAY_CHOICES = [
|
|
|
63
64
|
];
|
|
64
65
|
/** The Agent Inspector's dialog: loaded when it is first asked for. */
|
|
65
66
|
const AgentInspectorDialog = lazy(() => import('../../components/inspector/AgentInspectorDialog'));
|
|
67
|
+
/** *Agent Details…*: loaded when it is first asked for. */
|
|
68
|
+
const AgentDetailsDialog = lazy(() => import('./AgentDetailsDialog'));
|
|
69
|
+
/** *Code Sandbox Details…*: loaded when it is first asked for. */
|
|
70
|
+
const SandboxDetailsDialog = lazy(() => import('./SandboxDetailsDialog'));
|
|
66
71
|
/**
|
|
67
72
|
* The entries of the assistant's menu, composed from what the host passes:
|
|
68
73
|
* each shows when what it does is there to do.
|
|
@@ -77,6 +82,22 @@ export function assistantMenuItems(options) {
|
|
|
77
82
|
onSelect: options.inspect,
|
|
78
83
|
});
|
|
79
84
|
}
|
|
85
|
+
if (options.agentDetails) {
|
|
86
|
+
items.push({
|
|
87
|
+
id: 'agent-details',
|
|
88
|
+
label: 'Agent Details…',
|
|
89
|
+
icon: DependabotIcon,
|
|
90
|
+
onSelect: options.agentDetails,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (options.sandboxDetails) {
|
|
94
|
+
items.push({
|
|
95
|
+
id: 'sandbox-details',
|
|
96
|
+
label: 'Code Sandbox Details…',
|
|
97
|
+
icon: CodeIcon,
|
|
98
|
+
onSelect: options.sandboxDetails,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
80
101
|
if (options.conversationLabel !== false) {
|
|
81
102
|
items.push({
|
|
82
103
|
id: 'conversation',
|
|
@@ -335,7 +356,7 @@ export function useMouth(stageRef, mouthLevel, speaking) {
|
|
|
335
356
|
};
|
|
336
357
|
}, [stageRef, mouthLevel, speaking]);
|
|
337
358
|
}
|
|
338
|
-
export function AssistantStage({ character, state, size = 88, place, stageRef, onDragStart, open, onToggle, balloon, insist = false, onDismiss, ownRef, decide, mouthLevel, stayPut = false, balloonDisplay = 'history', expandTarget, expandOnArrival = false, suggestions, onSuggestion, inspector, inspectAgent, conversationLabel, onBalloonDisplayChange, onStop, onNewChat, onClear, onChangeCharacter, speech, onResetPosition, about, contextMenu, }) {
|
|
359
|
+
export function AssistantStage({ character, state, size = 88, place, stageRef, onDragStart, open, onToggle, onCharacterClick, onCharacterKeyDown, balloon, insist = false, onDismiss, ownRef, decide, mouthLevel, stayPut = false, balloonDisplay = 'history', expandTarget, expandOnArrival = false, suggestions, onSuggestion, inspector, inspectAgent, conversationLabel, onBalloonDisplayChange, onStop, onNewChat, onClear, onChangeCharacter, speech, onResetPosition, about, sandbox, contextMenu, agentName, label, }) {
|
|
339
360
|
// A shipped one by id, a drawing contributed by a plugin (T-24), or a
|
|
340
361
|
// character read from a file (T-26).
|
|
341
362
|
const shipped = typeof character === 'string'
|
|
@@ -343,9 +364,14 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
343
364
|
: 'Drawing' in character
|
|
344
365
|
? character
|
|
345
366
|
: undefined;
|
|
346
|
-
const
|
|
367
|
+
const characterName = shipped
|
|
347
368
|
? shipped.name
|
|
348
369
|
: character.name;
|
|
370
|
+
// The agent's name where the host gives it, else the character's.
|
|
371
|
+
const name = agentName ?? characterName;
|
|
372
|
+
// The character, as the figure's description, when it is not its name.
|
|
373
|
+
const describedBy = useId();
|
|
374
|
+
const described = Boolean(agentName || label);
|
|
349
375
|
// Drawn for the chat's colour mode: the dark drawing on a dark page (T-25).
|
|
350
376
|
const { colorScheme } = useTheme();
|
|
351
377
|
const colorMode = colorScheme?.startsWith('dark') ? 'dark' : 'light';
|
|
@@ -355,13 +381,19 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
355
381
|
const [menuAt, setMenuAt] = useState(null);
|
|
356
382
|
const [inspecting, setInspecting] = useState(false);
|
|
357
383
|
const [telling, setTelling] = useState(false);
|
|
384
|
+
const [detailing, setDetailing] = useState(null);
|
|
358
385
|
const characterRef = useRef(null);
|
|
359
386
|
const longPress = useRef(undefined);
|
|
360
387
|
const closeMenu = useCallback(() => setMenuAt(null), []);
|
|
361
388
|
useEffect(() => () => clearTimeout(longPress.current), []);
|
|
362
389
|
// Where the press began: a press that moves is a drag, not a click.
|
|
363
390
|
const pressedAt = useRef(null);
|
|
364
|
-
const aside = useKeepClear(stageRef, ownRef, menuOpen ||
|
|
391
|
+
const aside = useKeepClear(stageRef, ownRef, menuOpen ||
|
|
392
|
+
menuAt !== null ||
|
|
393
|
+
inspecting ||
|
|
394
|
+
telling ||
|
|
395
|
+
detailing !== null ||
|
|
396
|
+
stayPut);
|
|
365
397
|
useMouth(stageRef, mouthLevel, state === 'speaking');
|
|
366
398
|
// A decision being asked, or its answer, keeps the balloon up.
|
|
367
399
|
const [deciding, setDeciding] = useState(false);
|
|
@@ -379,6 +411,8 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
379
411
|
onDismiss,
|
|
380
412
|
conversationLabel,
|
|
381
413
|
inspect: inspector ? () => setInspecting(true) : undefined,
|
|
414
|
+
agentDetails: about ? () => setDetailing('agent') : undefined,
|
|
415
|
+
sandboxDetails: sandbox ? () => setDetailing('sandbox') : undefined,
|
|
382
416
|
balloonDisplay,
|
|
383
417
|
onBalloonDisplayChange,
|
|
384
418
|
suggestions,
|
|
@@ -410,7 +444,7 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
410
444
|
const historyVisual = balloonDisplay !== 'current' && history && history.length > 0
|
|
411
445
|
? {
|
|
412
446
|
id: 'balloon-history',
|
|
413
|
-
title: conversationHeaderText(history
|
|
447
|
+
title: conversationHeaderText(conversationCount(history)),
|
|
414
448
|
shrink: true,
|
|
415
449
|
render: () => (_jsx(BalloonHistoryLarge, { history: history, tool: balloon?.tool, attachment: balloon?.attachment })),
|
|
416
450
|
}
|
|
@@ -530,7 +564,8 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
530
564
|
: undefined, suggestions: waitsForQuestion ? suggestions : undefined, fullText: balloon.fullText, waiting: (state === 'thinking' ||
|
|
531
565
|
state === 'working' ||
|
|
532
566
|
state === 'waiting') &&
|
|
533
|
-
!balloon.speaking, onSuggestion: onSuggestion, decide: decide, onDecisionActive: setDeciding, wide: deciding, onOpen: onToggle, above: size + 8, side: balloonSide(place).side, align: balloonSide(place).align, tailAt: size / 2 }) })),
|
|
567
|
+
!balloon.speaking, onSuggestion: onSuggestion, decide: decide, onDecisionActive: setDeciding, wide: deciding, onOpen: onToggle, above: size + 8, side: balloonSide(place).side, align: balloonSide(place).align, tailAt: size / 2 }) })), _jsxs(Box, { as: "button", type: "button", "aria-label": label ??
|
|
568
|
+
(open ? `Close the conversation with ${name}` : `Talk to ${name}`), "aria-describedby": described ? describedBy : undefined, "aria-expanded": open, "aria-haspopup": "menu", ref: characterRef, "data-assistant-figure": "", onContextMenu: (event) => {
|
|
534
569
|
event.preventDefault();
|
|
535
570
|
clearTimeout(longPress.current);
|
|
536
571
|
setMenuAt({ x: event.clientX, y: event.clientY });
|
|
@@ -539,7 +574,9 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
539
574
|
event.preventDefault();
|
|
540
575
|
const box = event.currentTarget.getBoundingClientRect();
|
|
541
576
|
setMenuAt({ x: box.left + box.width / 2, y: box.bottom });
|
|
577
|
+
return;
|
|
542
578
|
}
|
|
579
|
+
onCharacterKeyDown?.(event);
|
|
543
580
|
}, onPointerUp: () => clearTimeout(longPress.current), onPointerCancel: () => clearTimeout(longPress.current), onPointerMove: (event) => {
|
|
544
581
|
const from = pressedAt.current;
|
|
545
582
|
if (from &&
|
|
@@ -565,7 +602,7 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
565
602
|
Math.hypot(event.clientX - from.x, event.clientY - from.y) > 4) {
|
|
566
603
|
return;
|
|
567
604
|
}
|
|
568
|
-
onToggle();
|
|
605
|
+
(onCharacterClick ?? onToggle)();
|
|
569
606
|
}, sx: {
|
|
570
607
|
display: 'block',
|
|
571
608
|
width: size,
|
|
@@ -583,13 +620,26 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
583
620
|
outlineOffset: 2,
|
|
584
621
|
borderRadius: '50%',
|
|
585
622
|
},
|
|
586
|
-
}, children:
|
|
623
|
+
}, children: [described && (_jsx(Box, { as: "span", id: describedBy, sx: {
|
|
624
|
+
position: 'absolute',
|
|
625
|
+
width: 1,
|
|
626
|
+
height: 1,
|
|
627
|
+
overflow: 'hidden',
|
|
628
|
+
clip: 'rect(0 0 0 0)',
|
|
629
|
+
whiteSpace: 'nowrap',
|
|
630
|
+
}, children: `Its character: ${characterName}` })), shipped ? (_jsx(shipped.Drawing, { size: size, mode: colorMode })) : (_jsx(SpriteCharacter, { character: character, state: state, size: size }))] }), (hovered || menuOpen) && !aside && state !== 'goodbye' && (_jsx(Box, { sx: { position: 'absolute', top: '-6px', right: '-6px' }, children: _jsxs(ActionMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: XIcon, "aria-label": `Send ${name} away`, size: "small", variant: "invisible", "data-assistant-dismiss": "", sx: {
|
|
587
631
|
bg: 'canvas.default',
|
|
588
632
|
borderRadius: '50%',
|
|
589
633
|
boxShadow: 'shadow.small',
|
|
590
634
|
} }) }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsx(ActionList, { children: AWAY_CHOICES.map(choice => (_jsx(ActionList.Item, { "data-assistant-away": choice.away, onSelect: () => onDismiss(choice.away), children: choice.label }, choice.away))) }) })] }) })), _jsx(AssistantContextMenu, { at: menuAt, items: menuItems, onClose: closeMenu, returnFocusRef: characterRef, label: `${name}\u2019s menu` }), inspecting && (_jsx(Suspense, { fallback: null, children: _jsx(AgentInspectorDialog, { sink: inspector ?? null, agent: inspectAgent, title: `${about?.name ?? name} \u00b7 Agent Inspector`, onClose: () => {
|
|
591
635
|
setInspecting(false);
|
|
592
636
|
characterRef.current?.focus();
|
|
637
|
+
} }) })), detailing === 'agent' && about && (_jsx(Suspense, { fallback: null, children: _jsx(AgentDetailsDialog, { about: about, name: name, onClose: () => {
|
|
638
|
+
setDetailing(null);
|
|
639
|
+
characterRef.current?.focus();
|
|
640
|
+
} }) })), detailing === 'sandbox' && sandbox && (_jsx(Suspense, { fallback: null, children: _jsx(SandboxDetailsDialog, { sandbox: sandbox, name: about?.name ?? name, onClose: () => {
|
|
641
|
+
setDetailing(null);
|
|
642
|
+
characterRef.current?.focus();
|
|
593
643
|
} }) })), telling && about && (_jsx(Dialog, { title: `About ${about.name ?? name}`, onClose: () => {
|
|
594
644
|
setTelling(false);
|
|
595
645
|
characterRef.current?.focus();
|
|
@@ -598,7 +648,7 @@ export function AssistantStage({ character, state, size = 88, place, stageRef, o
|
|
|
598
648
|
['Spec', about.spec],
|
|
599
649
|
['Model', about.model],
|
|
600
650
|
['Runs', about.where],
|
|
601
|
-
['Character',
|
|
651
|
+
['Character', characterName],
|
|
602
652
|
]
|
|
603
653
|
.filter(([, value]) => value)
|
|
604
654
|
.map(([key, value]) => (_jsxs(Text, { as: "p", sx: { m: 0, mb: 1 }, children: [_jsxs(Text, { sx: { color: 'fg.muted' }, children: [key, ": "] }), value] }, key))) }))] }));
|
|
@@ -7,15 +7,29 @@
|
|
|
7
7
|
* @module chat/assistant/BalloonParts
|
|
8
8
|
*/
|
|
9
9
|
import type { JSX, ReactNode } from 'react';
|
|
10
|
+
import { type ChatDensity } from '../messages/ChatMarkdown';
|
|
11
|
+
import type { DisplayItem } from '../../types/chat';
|
|
10
12
|
import { type BalloonToolLine } from './toolLine';
|
|
11
13
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* The conversation's items in the balloon, drawn by the chat's own
|
|
15
|
+
* components (`ChatMessageList`): markdown, code blocks, tool calls and
|
|
16
|
+
* their approvals, notes, the three dots — in the compact density, or the
|
|
17
|
+
* chat's own when drawn large.
|
|
18
|
+
*/
|
|
19
|
+
export declare function BalloonChatItems({ items, density, waiting, }: {
|
|
20
|
+
items: readonly DisplayItem[];
|
|
21
|
+
density?: ChatDensity;
|
|
22
|
+
/** At work with nothing written yet: the chat's dots, last. */
|
|
23
|
+
waiting?: boolean;
|
|
24
|
+
}): JSX.Element;
|
|
25
|
+
/**
|
|
26
|
+
* The tool being called, in the balloon: the chat's tool call card, compact,
|
|
27
|
+
* with its runtime's own words (`Asking Accounting…`) as its summary.
|
|
15
28
|
* Seen, not read out: {@link ToolLineAnnouncer} says it once per change.
|
|
16
29
|
*/
|
|
17
|
-
export declare function
|
|
30
|
+
export declare function BalloonToolCall({ line, waiting, }: {
|
|
18
31
|
line: BalloonToolLine;
|
|
32
|
+
waiting?: boolean;
|
|
19
33
|
}): JSX.Element;
|
|
20
34
|
/**
|
|
21
35
|
* What a screen reader hears of the tool lines, politely: once when a call
|