@datalayer/agent-runtimes 1.3.89 → 1.3.91
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/Agent.js +2 -18
- package/lib/AgentDocument.js +5 -55
- package/lib/AgentNode.js +31 -208
- package/lib/AgentNotebook.js +5 -59
- package/lib/agent-node/AgentNodeGallery.js +23 -111
- package/lib/agents/AgentDetails.js +36 -274
- package/lib/agents/AgentRuntimeChat.js +1 -8
- package/lib/chat/Chat.js +7 -46
- package/lib/chat/ChatFloating.js +15 -100
- package/lib/chat/ChatInline.js +5 -47
- package/lib/chat/ChatPopupStandalone.js +5 -53
- package/lib/chat/ChatSidebar.js +4 -51
- package/lib/chat/ChatStandalone.js +4 -45
- package/lib/chat/EphemeralSurfaceControl.js +5 -25
- package/lib/chat/assistant/AssistantContextMenu.d.ts +8 -0
- package/lib/chat/assistant/AssistantContextMenu.js +17 -1
- package/lib/chat/assistant/AssistantStage.js +6 -25
- package/lib/chat/assistant/BalloonParts.js +8 -40
- package/lib/chat/assistant/BalloonVisual.js +2 -2
- package/lib/chat/assistant/ConversationBalloon.js +2 -11
- package/lib/chat/assistant/DecisionAsk.js +3 -3
- package/lib/chat/assistant/SandboxDetailsDialog.js +3 -17
- package/lib/chat/assistant/SpeechBalloon.js +14 -78
- package/lib/chat/base/ChatBase.js +37 -172
- package/lib/chat/display/EmptyState.js +7 -35
- package/lib/chat/display/FloatingBrandButton.js +4 -34
- package/lib/chat/display/PoweredByTag.js +3 -14
- package/lib/chat/document/EphemeralDocument.js +3 -18
- package/lib/chat/header/ChatHeader.js +1 -17
- package/lib/chat/header/ChatHeaderBase.js +2 -24
- package/lib/chat/header/ChatViewModeToggle.js +7 -29
- package/lib/chat/indicators/McpStatusIndicator.js +3 -12
- package/lib/chat/indicators/SandboxStatusIndicator.js +6 -34
- package/lib/chat/indicators/SkillsStatusIndicator.js +3 -12
- package/lib/chat/indicators/TypingDots.js +1 -11
- package/lib/chat/messages/ChatMessageList.js +58 -185
- package/lib/chat/messages/ChatMessages.js +15 -79
- package/lib/chat/messages/FormSubmissionMessage.js +2 -33
- package/lib/chat/messages/NotebookToolSurfaces.js +12 -41
- package/lib/chat/messages/TurnFooter.js +4 -10
- package/lib/chat/notebook/EphemeralNotebook.js +2 -10
- package/lib/chat/parts/ReasoningPart.js +2 -16
- package/lib/chat/parts/TextPart.js +2 -12
- package/lib/chat/parts/ToolPart.js +16 -90
- package/lib/chat/presence/Presence.js +5 -33
- package/lib/chat/prompt/FloatingCard.js +1 -13
- package/lib/chat/prompt/InputPrompt.js +1 -6
- package/lib/chat/prompt/InputPromptBase.js +4 -17
- package/lib/chat/prompt/InputPromptLexical.js +44 -45
- package/lib/chat/prompt/InputPromptText.js +1 -1
- package/lib/chat/prompt/footer/InPromptFooter.js +1 -8
- package/lib/chat/prompt/menus/AgentsMenu.js +1 -1
- package/lib/chat/prompt/menus/InlineAgentsMenu.js +1 -1
- package/lib/chat/prompt/menus/ModelSelector.js +1 -5
- package/lib/chat/prompt/menus/SkillsMenu.js +3 -30
- package/lib/chat/prompt/menus/SuggestionsMenu.js +1 -1
- package/lib/chat/prompt/menus/ToolsMenu.js +4 -48
- package/lib/chat/prompt/plugins/AgentMentionPlugin.js +2 -9
- package/lib/chat/prompt/plugins/CommandPlugin.js +2 -9
- package/lib/chat/prompt/plugins/MentionChip.js +1 -15
- package/lib/chat/prompt/stack.js +1 -19
- package/lib/chat/tools/A2AAgentDialog.js +9 -42
- package/lib/chat/tools/SubagentActivity.js +5 -22
- package/lib/chat/tools/ToolApprovalBanner.js +4 -34
- package/lib/chat/tools/ToolApprovalDialog.js +4 -19
- package/lib/chat/tools/ToolCallDisplay.js +12 -97
- package/lib/chat/usage/ContextPie.js +4 -45
- package/lib/chat/words.d.ts +7 -0
- package/lib/chat/words.js +12 -0
- package/lib/components/a2ui/datalayer/Chart.js +4 -10
- package/lib/components/a2ui/datalayer/Chat.js +2 -10
- package/lib/components/a2ui/datalayer/Download.js +1 -1
- package/lib/components/a2ui/datalayer/Evidence.js +1 -15
- package/lib/components/a2ui/datalayer/FileUpload.js +1 -12
- package/lib/components/a2ui/datalayer/Table.js +9 -17
- package/lib/components/a2ui/datalayer/formWidgets.js +3 -2
- package/lib/components/a2ui/datalayer/parts.js +1 -16
- package/lib/components/a2ui/styles.js +16 -5
- package/lib/components/agents/AgentSummary.js +1 -51
- package/lib/components/cards/NotificationEventCard.js +6 -72
- package/lib/components/cards/OutputCard.js +4 -48
- package/lib/components/cards/ToolApprovalCard.js +2 -35
- package/lib/components/code-sandboxes/CodeSandboxCellVariables.js +1 -1
- package/lib/components/code-sandboxes/CodeSandboxEnvironmentSelect.js +4 -14
- package/lib/components/code-sandboxes/CodeSandboxPicker.js +16 -21
- package/lib/components/code-sandboxes/CodeSandboxVariables.js +2 -2
- package/lib/components/scheduler/ScheduleMenu.js +5 -10
- package/lib/components/specs/SpecPayloadPreview.js +1 -26
- package/lib/components/teams/A2ATeamGraph.d.ts +4 -3
- package/lib/components/teams/A2ATeamGraph.js +25 -71
- package/lib/components/teams/AnswerSurfacesView.js +2 -2
- package/lib/components/teams/NotebookPreview.js +1 -10
- package/lib/components/teams/NotebookPreviewView.js +2 -3
- package/lib/components/teams/SceneTranscript.js +3 -17
- package/lib/components/teams/SceneView.js +1 -8
- package/lib/components/teams/TeamNotebook.js +5 -13
- package/lib/components/teams/TeamNotebookView.js +2 -12
- package/lib/components/teams/index.d.ts +1 -0
- package/lib/components/teams/index.js +1 -0
- package/lib/components/teams/useBalloonRoom.d.ts +39 -0
- package/lib/components/teams/useBalloonRoom.js +89 -0
- package/lib/config/AgentConfiguration.js +22 -225
- package/lib/context/ContextDistribution.js +7 -41
- package/lib/context/ContextInspector.js +9 -107
- package/lib/context/ContextPanel.js +11 -86
- package/lib/context/ContextUsage.js +6 -34
- package/lib/context/CostTracker.js +7 -42
- package/lib/context/MessageHistory.js +3 -37
- package/lib/context/TurnGraphChart.js +9 -41
- package/lib/examples/A2UiAgentExample.js +6 -108
- package/lib/examples/A2UiComponentsGalleryExample.js +1 -1
- package/lib/examples/A2UiContactCardExample.js +1 -1
- package/lib/examples/A2UiJupyterOutputExample.js +25 -125
- package/lib/examples/A2UiRestaurantExample.js +1 -1
- package/lib/examples/A2UiViewerExample.js +1 -1
- package/lib/examples/AgUiAgenticExample.js +3 -35
- package/lib/examples/AgUiBackendToolRenderingExample.js +2 -25
- package/lib/examples/AgUiHaikuGenUiExample.js +2 -32
- package/lib/examples/AgUiHumanInTheLoopExample.js +5 -59
- package/lib/examples/AgUiSharedStateExample.js +6 -56
- package/lib/examples/AgUiToolsBasedGenUiExample.js +25 -120
- package/lib/examples/AgentA2AExample.js +1 -15
- package/lib/examples/AgentA2ATeamExample.js +6 -30
- package/lib/examples/AgentCheckpointsExample.js +11 -145
- package/lib/examples/AgentCodeSandboxExample.js +5 -108
- package/lib/examples/AgentCodeSandboxesExample.js +3 -30
- package/lib/examples/AgentCodemodeExample.js +9 -85
- package/lib/examples/AgentCompactionExample.js +3 -64
- package/lib/examples/AgentDecideExample.js +1 -13
- package/lib/examples/AgentEvalsExample.js +5 -60
- package/lib/examples/AgentGuardrailsExample.js +4 -28
- package/lib/examples/AgentHooksExample.js +1 -1
- package/lib/examples/AgentInferenceProviderExample.js +5 -96
- package/lib/examples/AgentMCPExample.js +7 -105
- package/lib/examples/AgentMemoryExample.js +5 -74
- package/lib/examples/AgentMonitoringExample.js +7 -53
- package/lib/examples/AgentNotificationsExample.js +3 -61
- package/lib/examples/AgentOtelExample.js +3 -72
- package/lib/examples/AgentOutputsExample.js +6 -81
- package/lib/examples/AgentParametersExample.js +2 -37
- package/lib/examples/AgentSkillsExample.js +3 -45
- package/lib/examples/AgentSubagentsExample.js +6 -56
- package/lib/examples/AgentToolApprovalsExample.js +1 -11
- package/lib/examples/AgentTriggersExample.js +29 -239
- package/lib/examples/AgentspecsExample.js +6 -60
- package/lib/examples/AssistantExample.js +5 -5
- package/lib/examples/AssistantGalleryExample.js +8 -65
- package/lib/examples/CellExample.js +1 -6
- package/lib/examples/ChatCustomExample.js +2 -31
- package/lib/examples/ChatExample.js +1 -9
- package/lib/examples/ChatStandaloneExample.js +3 -37
- package/lib/examples/CopilotKitLexicalExample.js +1 -24
- package/lib/examples/DecksAgent.js +1 -1
- package/lib/examples/DocumentPageAgent.js +1 -1
- package/lib/examples/HomeExample.js +14 -62
- package/lib/examples/Lexical2Example.js +3 -32
- package/lib/examples/LexicalAgentExample.js +2 -34
- package/lib/examples/LexicalAgentSidebarExample.js +3 -34
- package/lib/examples/LoopAppComputerExample.js +1 -1
- package/lib/examples/LoopShellExample.js +2 -2
- package/lib/examples/LoopStrategyExample.js +15 -87
- package/lib/examples/LoopWorkspaceEmbed.js +2 -18
- package/lib/examples/LoopWorkspaceExample.js +2 -2
- package/lib/examples/NotebookAgentExample.js +2 -33
- package/lib/examples/NotebookAgentSidebarExample.js +3 -46
- package/lib/examples/NotebookCollaborationExample.js +1 -31
- package/lib/examples/NotebookExample.js +1 -18
- package/lib/examples/NotebookPageAgent.js +1 -1
- package/lib/examples/ScenesExample.js +5 -24
- package/lib/examples/VoiceChatExample.js +1 -1
- package/lib/examples/components/AuthRequiredView.js +1 -7
- package/lib/examples/components/ErrorView.js +1 -8
- package/lib/examples/components/ExampleErrorBoundary.js +1 -14
- package/lib/examples/components/FooterMetrics.js +1 -7
- package/lib/examples/components/Header.js +12 -51
- package/lib/examples/components/HeaderControls.js +1 -9
- package/lib/examples/components/LexicalEditor.js +1 -8
- package/lib/examples/components/MainContent.js +1 -13
- package/lib/examples/components/MockFileBrowser.js +4 -40
- package/lib/examples/components/SessionTabs.js +1 -1
- package/lib/examples/components/TimeTravel.js +1 -13
- package/lib/examples/main.js +13 -81
- package/lib/examples/scenes/A2UiComponentsGalleryScene.js +3 -34
- package/lib/examples/scenes/A2UiContactCardScene.js +3 -35
- package/lib/examples/scenes/A2UiRestaurantScene.js +3 -53
- package/lib/examples/scenes/A2UiViewerScene.js +3 -34
- package/lib/examples/utils/AssistantGalleryGrid.js +6 -35
- package/lib/examples2/DatalayerNotebookExample.js +3 -33
- package/lib/examples2/NativeNavigationExample.js +4 -10
- package/lib/examples2/NotebookMutationsKernel.js +2 -1
- package/lib/examples2/NotebookMutationsServiceManager.js +2 -1
- package/lib/examples2/ReactRouterExample.js +14 -42
- package/lib/hooks/useToolApprovals.d.ts +2 -34
- package/lib/hooks/useToolApprovals.js +1 -64
- package/lib/identity/AgentIdentity.js +17 -62
- package/lib/identity/IdentityConnect.js +13 -59
- package/lib/identity/OAuthCallback.js +6 -44
- package/lib/lexical/ChatInlinePlugin.js +6 -14
- package/lib/loop/apps/AppFeedback.js +12 -3
- package/lib/loop/apps/AppRenderer.d.ts +4 -3
- package/lib/loop/apps/AppRenderer.js +11 -12
- package/lib/loop/apps/appspec.js +6 -3
- package/lib/loop/apps/feedback.d.ts +3 -2
- package/lib/loop/apps/feedback.js +4 -2
- package/lib/loop/core/index.d.ts +19 -0
- package/lib/loop/core/index.js +27 -0
- package/lib/loop/embed/AppEmbed.d.ts +1 -1
- package/lib/loop/embed/AppEmbed.js +2 -1
- package/lib/loop/embed/LoopEmbed.js +1 -7
- package/lib/loop/embed/embedConfig.d.ts +3 -3
- package/lib/loop/embed/embedConfig.js +2 -3
- package/lib/loop/embed/embedTheme.d.ts +4 -4
- package/lib/loop/embed/embedTheme.js +11 -7
- package/lib/loop/plugins/a2a-sidebar/A2ASidebar.js +7 -34
- package/lib/loop/plugins/a2ui/A2uiView.js +4 -12
- package/lib/loop/plugins/a2ui-surface/InlineSurface.js +1 -16
- package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.js +2 -12
- package/lib/loop/plugins/agents/AnonymousKeyBadge.js +3 -2
- package/lib/loop/plugins/agents/SandboxSelector.js +3 -7
- package/lib/loop/plugins/agents/SandboxView.js +4 -27
- package/lib/loop/plugins/agents/TeamMemberPicker.js +2 -2
- package/lib/loop/plugins/agentspecs/AgentspecPicker.js +3 -2
- package/lib/loop/plugins/app-activity/AppActivity.js +1 -1
- package/lib/loop/plugins/app-computer/AppComputer.js +32 -27
- package/lib/loop/plugins/app-elements/AppElements.js +2 -31
- package/lib/loop/plugins/app-page/AppPage.js +26 -8
- package/lib/loop/plugins/app-rules/AppRulesCard.js +4 -20
- package/lib/loop/plugins/assistant/index.js +1 -13
- package/lib/loop/plugins/chat/ChatView.js +89 -130
- package/lib/loop/plugins/checkpoints-sidebar/CheckpointsSidebar.js +2 -13
- package/lib/loop/plugins/decks/DeckSurface.js +2 -2
- package/lib/loop/plugins/document/DocumentView.js +4 -12
- package/lib/loop/plugins/document-toolbar/SandboxStatusItem.js +3 -8
- package/lib/loop/plugins/graph/GraphView.js +2 -2
- package/lib/loop/plugins/input-prompt/ComposerView.js +1 -1
- package/lib/loop/plugins/notebook/NotebookView.js +3 -11
- package/lib/loop/plugins/page-layout/SplitLayout.js +11 -34
- package/lib/loop/plugins/page-layout/TurnPanel.js +9 -35
- package/lib/loop/plugins/shell/useEditorPreviews.js +3 -2
- package/lib/loop/plugins/subagent-activity/SubagentPulse.js +1 -13
- package/lib/loop/plugins/window-frame/WindowFrame.js +10 -44
- package/lib/loop/plugins/window-frame/index.js +1 -1
- package/lib/loop/shell/LoopWorkspace.js +34 -77
- package/lib/loop/shell/PluginToggles.js +4 -15
- package/lib/loop/shell/SidebarRail.js +8 -40
- package/lib/loop/shell/ViewSwitcher.js +4 -24
- package/lib/loop-main.js +2 -3
- package/lib/mcp/McpServerManager.js +6 -37
- package/lib/portable/index.d.ts +11 -0
- package/lib/portable/index.js +20 -0
- package/lib/protocols/AGUIAdapter.js +2 -2
- package/lib/protocols/BaseProtocolAdapter.d.ts +2 -0
- package/lib/protocols/BaseProtocolAdapter.js +4 -0
- package/lib/specs/apps.js +6 -0
- package/lib/specs/appspecSchema.js +11 -4
- package/lib/stories/loop/ReferenceScreens.js +17 -91
- package/lib/stories/loop/pictures-main.js +1 -1
- package/lib/types/agentspecs.d.ts +5 -2
- package/lib/types/protocol.d.ts +2 -0
- package/lib/utils/approvals.d.ts +59 -0
- package/lib/utils/approvals.js +101 -0
- package/lib/voice/VoiceInput.js +3 -39
- package/package.json +2 -2
- package/lib/shims/primerAddonsBox.d.ts +0 -1
- package/lib/shims/primerAddonsBox.js +0 -7
|
@@ -68,39 +68,16 @@ export function SplitLayout({ editors, hasEditor, transcript, prompt, chips, pic
|
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
70
|
const percent = Math.round(share * 100);
|
|
71
|
-
return (_jsxs(Box, { "data-testid": "loop-split-layout",
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
position: 'relative',
|
|
82
|
-
overflow: 'hidden',
|
|
83
|
-
}, children: [_jsxs(Box, { "data-testid": "loop-split-conversation", sx: {
|
|
84
|
-
flex: hasEditor ? `0 0 ${percent}%` : '1 1 auto',
|
|
85
|
-
minWidth: 0,
|
|
86
|
-
minHeight: 0,
|
|
87
|
-
display: 'flex',
|
|
88
|
-
flexDirection: 'column',
|
|
89
|
-
// The transcript draws a rule on its left when an editor is on
|
|
90
|
-
// screen, for the split it sits on the right of. Here it is on
|
|
91
|
-
// the left, and the hairline is the separator: the rule is
|
|
92
|
-
// pushed out of the row, which clips it.
|
|
93
|
-
ml: hasEditor ? '-1px' : 0,
|
|
94
|
-
}, children: [transcript, chips, prompt] }), hasEditor ? (_jsx(Box, { role: "separator", "aria-orientation": "vertical", "aria-label": "Resize the conversation and the page", "aria-valuemin": Math.round(SPLIT_MIN_SHARE * 100), "aria-valuemax": Math.round(SPLIT_MAX_SHARE * 100), "aria-valuenow": percent, tabIndex: 0, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onKeyDown: onKeyDown, sx: {
|
|
95
|
-
// A hairline to the eye, a few pixels to the pointer.
|
|
96
|
-
flex: '0 0 7px',
|
|
97
|
-
mx: '-3px',
|
|
98
|
-
zIndex: 1,
|
|
99
|
-
cursor: 'col-resize',
|
|
100
|
-
touchAction: 'none',
|
|
101
|
-
display: 'flex',
|
|
102
|
-
justifyContent: 'center',
|
|
103
|
-
outline: 'none',
|
|
71
|
+
return (_jsxs(Box, { "data-testid": "loop-split-layout", flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column", children: [picker, _jsxs(Box, { ref: row, flex: "1 1 auto", minHeight: 0, display: "flex",
|
|
72
|
+
// The hidden editors position themselves against this row.
|
|
73
|
+
position: "relative", overflow: "hidden", children: [_jsxs(Box, { "data-testid": "loop-split-conversation", flex: hasEditor ? `0 0 ${percent}%` : '1 1 auto', minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column",
|
|
74
|
+
// The transcript draws a rule on its left when an editor is on
|
|
75
|
+
// screen, for the split it sits on the right of. Here it is on
|
|
76
|
+
// the left, and the hairline is the separator: the rule is
|
|
77
|
+
// pushed out of the row, which clips it.
|
|
78
|
+
ml: hasEditor ? '-1px' : 0, children: [transcript, chips, prompt] }), hasEditor ? (_jsx(Box, { role: "separator", "aria-orientation": "vertical", "aria-label": "Resize the conversation and the page", "aria-valuemin": Math.round(SPLIT_MIN_SHARE * 100), "aria-valuemax": Math.round(SPLIT_MAX_SHARE * 100), "aria-valuenow": percent, tabIndex: 0, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onKeyDown: onKeyDown,
|
|
79
|
+
// A hairline to the eye, a few pixels to the pointer.
|
|
80
|
+
flex: "0 0 7px", mx: "-3px", zIndex: 1, cursor: "col-resize", display: "flex", justifyContent: "center", outline: "none", touchAction: "none", sx: {
|
|
104
81
|
'&::before': {
|
|
105
82
|
content: '""',
|
|
106
83
|
width: '1px',
|
|
@@ -110,7 +87,7 @@ export function SplitLayout({ editors, hasEditor, transcript, prompt, chips, pic
|
|
|
110
87
|
'&:hover::before, &:focus-visible::before': {
|
|
111
88
|
width: '3px',
|
|
112
89
|
bg: 'accent.emphasis',
|
|
113
|
-
}
|
|
90
|
+
}
|
|
114
91
|
} })) : null, _jsx(Box, { "data-testid": "loop-split-page", sx: hasEditor
|
|
115
92
|
? {
|
|
116
93
|
flex: '1 1 0',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { Box
|
|
3
|
+
import { Box } from '@datalayer/primer-addons';
|
|
4
|
+
import { IconButton, Text } from '@primer/react';
|
|
4
5
|
import { CheckIcon, CommentDiscussionIcon, CopyIcon, XIcon, } from '@primer/octicons-react';
|
|
5
6
|
import { useContributions, useSignalValue } from '@datalayer/reactor/react';
|
|
6
7
|
import { signal } from '@datalayer/reactor';
|
|
@@ -16,10 +17,7 @@ const NO_TURN = signal({ id: 0, status: 'idle' });
|
|
|
16
17
|
const MAX_HEIGHT = 168;
|
|
17
18
|
/** The three dots, while the agent has said nothing yet. */
|
|
18
19
|
function Thinking() {
|
|
19
|
-
return (_jsxs(Box, { as: "span", "aria-label": "The agent is thinking", sx: {
|
|
20
|
-
display: 'inline-flex',
|
|
21
|
-
gap: '4px',
|
|
22
|
-
alignItems: 'center',
|
|
20
|
+
return (_jsxs(Box, { as: "span", "aria-label": "The agent is thinking", display: "inline-flex", gap: "4px", alignItems: "center", sx: {
|
|
23
21
|
height: '1.5em',
|
|
24
22
|
'& > i': {
|
|
25
23
|
width: 5,
|
|
@@ -75,17 +73,7 @@ export function TurnPanel({ footer = 'full', }) {
|
|
|
75
73
|
return null;
|
|
76
74
|
}
|
|
77
75
|
const working = turn.status === 'thinking' || turn.status === 'streaming';
|
|
78
|
-
return (_jsxs(Box, { "data-turn-panel": "", sx: {
|
|
79
|
-
borderTop: '1px solid',
|
|
80
|
-
borderColor: 'border.muted',
|
|
81
|
-
px: 3,
|
|
82
|
-
pt: 2,
|
|
83
|
-
pb: footer === 'none' ? 2 : 1,
|
|
84
|
-
display: 'flex',
|
|
85
|
-
flexDirection: 'column',
|
|
86
|
-
gap: 2,
|
|
87
|
-
bg: 'canvas.default',
|
|
88
|
-
}, children: [_jsx(Box, { sx: { display: 'flex', justifyContent: 'flex-end' }, children: _jsx(Text, { sx: {
|
|
76
|
+
return (_jsxs(Box, { "data-turn-panel": "", borderTop: "1px solid", borderColor: "border.muted", px: 3, pt: 2, pb: footer === 'none' ? 2 : 1, display: "flex", flexDirection: "column", gap: 2, bg: "canvas.default", children: [_jsx(Box, { display: "flex", justifyContent: "flex-end", children: _jsx(Text, { sx: {
|
|
89
77
|
fontSize: 0,
|
|
90
78
|
lineHeight: 1.45,
|
|
91
79
|
px: 2,
|
|
@@ -98,29 +86,15 @@ export function TurnPanel({ footer = 'full', }) {
|
|
|
98
86
|
display: '-webkit-box',
|
|
99
87
|
WebkitLineClamp: 2,
|
|
100
88
|
WebkitBoxOrient: 'vertical',
|
|
101
|
-
}, children: turn.user }) }), _jsxs(Box, {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
overflowY: 'auto',
|
|
106
|
-
fontSize: 0,
|
|
107
|
-
lineHeight: 1.5,
|
|
108
|
-
color: turn.assistant ? 'fg.default' : 'fg.muted',
|
|
109
|
-
// Rendered markdown brings its own flow; the plain fallbacks
|
|
110
|
-
// below keep their line breaks.
|
|
111
|
-
whiteSpace: turn.assistant ? 'normal' : 'pre-wrap',
|
|
112
|
-
overflowWrap: 'anywhere',
|
|
113
|
-
}, children: turn.assistant ? (_jsx(Box, { sx: { ...streamdownMarkdownStyles, fontSize: 0 }, children: _jsx(Streamdown, { children: normalizeAssistantMarkdown(turn.assistant) }) })) : turn.activity ? (_jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: turn.activity })) : working ? (_jsx(Thinking, {})) : turn.status === 'error' ? ('The agent could not answer.') : ('Done — the result is in the page.') }), _jsx(IconButton, { icon: CommentDiscussionIcon, size: "small", variant: "invisible", "aria-label": "Open the conversation", onClick: openPagePanel, sx: { color: 'fg.muted', flexShrink: 0 } })] }), turn.assistant && turn.activity ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontStyle: 'italic' }, children: turn.activity })) : null, footer === 'full' ? (
|
|
89
|
+
}, children: turn.user }) }), _jsxs(Box, { display: "flex", gap: 2, alignItems: "flex-start", children: [_jsx(Box, { ref: replyRef, flex: "1 1 auto", minWidth: 0, maxHeight: MAX_HEIGHT, overflowY: "auto", fontSize: 0, lineHeight: 1.5, color: turn.assistant ? 'fg.default' : 'fg.muted',
|
|
90
|
+
// Rendered markdown brings its own flow; the plain fallbacks
|
|
91
|
+
// below keep their line breaks.
|
|
92
|
+
whiteSpace: turn.assistant ? 'normal' : 'pre-wrap', overflowWrap: "anywhere", children: turn.assistant ? (_jsx(Box, { sx: { ...streamdownMarkdownStyles, fontSize: 0 }, children: _jsx(Streamdown, { children: normalizeAssistantMarkdown(turn.assistant) }) })) : turn.activity ? (_jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: turn.activity })) : working ? (_jsx(Thinking, {})) : turn.status === 'error' ? ('The agent could not answer.') : ('Done — the result is in the page.') }), _jsx(IconButton, { icon: CommentDiscussionIcon, size: "small", variant: "invisible", "aria-label": "Open the conversation", onClick: openPagePanel, sx: { color: 'fg.muted', flexShrink: 0 } })] }), turn.assistant && turn.activity ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontStyle: 'italic' }, children: turn.activity })) : null, footer === 'full' ? (
|
|
114
93
|
// The same footer the transcript draws under a turn: the window's
|
|
115
94
|
// fill, this turn's tokens in and out, copy, and dismiss.
|
|
116
95
|
_jsx(TurnFooter, { usage: turn.usage, live: working, latest: true, padding: 0, onCopy: copyTurn, onRemove: () => setDismissedId(turn.id) })) : footer === 'actions' ? (
|
|
117
96
|
// The actions without the counters, for a host whose readers are not
|
|
118
97
|
// asking about tokens.
|
|
119
|
-
_jsxs(Box, { sx: {
|
|
120
|
-
display: 'flex',
|
|
121
|
-
justifyContent: 'flex-end',
|
|
122
|
-
gap: 1,
|
|
123
|
-
mt: -1,
|
|
124
|
-
}, children: [_jsx(IconButton, { icon: copied ? CheckIcon : CopyIcon, size: "small", variant: "invisible", "aria-label": copied ? 'Copied' : 'Copy this turn', onClick: () => void copyTurn(), sx: { color: 'fg.muted' } }), _jsx(IconButton, { icon: XIcon, size: "small", variant: "invisible", "aria-label": "Dismiss until the next turn", onClick: () => setDismissedId(turn.id), sx: { color: 'fg.muted' } })] })) : null] }));
|
|
98
|
+
_jsxs(Box, { display: "flex", justifyContent: "flex-end", gap: 1, mt: -1, children: [_jsx(IconButton, { icon: copied ? CheckIcon : CopyIcon, size: "small", variant: "invisible", "aria-label": copied ? 'Copied' : 'Copy this turn', onClick: () => void copyTurn(), sx: { color: 'fg.muted' } }), _jsx(IconButton, { icon: XIcon, size: "small", variant: "invisible", "aria-label": "Dismiss until the next turn", onClick: () => setDismissedId(turn.id), sx: { color: 'fg.muted' } })] })) : null] }));
|
|
125
99
|
}
|
|
126
100
|
export default TurnPanel;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useState, useSyncExternalStore } from 'react';
|
|
3
|
-
import { Box
|
|
3
|
+
import { Box } from '@datalayer/primer-addons';
|
|
4
|
+
import { Text } from '@primer/react';
|
|
4
5
|
import { getEditorChoice, subscribeEditorChoice } from './editorChoice';
|
|
5
6
|
let jupyterReact = null;
|
|
6
7
|
function loadJupyterReact() {
|
|
@@ -21,7 +22,7 @@ function stripped(source) {
|
|
|
21
22
|
}
|
|
22
23
|
/** The card's body: one row per cell or block. */
|
|
23
24
|
function PreviewList({ title, rows, }) {
|
|
24
|
-
return (_jsxs(Box, { children: [_jsx(Text, { sx: { fontWeight: 'semibold', display: 'block', mb: 1 }, children: title }), rows.length === 0 ? (_jsx(Text, { sx: { color: 'fg.muted' }, children: "Empty so far." })) : (rows.map((row, index) => (_jsxs(Box, {
|
|
25
|
+
return (_jsxs(Box, { children: [_jsx(Text, { sx: { fontWeight: 'semibold', display: 'block', mb: 1 }, children: title }), rows.length === 0 ? (_jsx(Text, { sx: { color: 'fg.muted' }, children: "Empty so far." })) : (rows.map((row, index) => (_jsxs(Box, { display: "flex", gap: 2, py: "2px", alignItems: "baseline", children: [_jsxs(Text, { sx: { color: 'fg.muted', flexShrink: 0, fontFamily: 'mono' }, children: [index, " \u00B7 ", row.kind] }), _jsx(Text, { sx: {
|
|
25
26
|
fontFamily: 'mono',
|
|
26
27
|
whiteSpace: 'nowrap',
|
|
27
28
|
overflow: 'hidden',
|
|
@@ -28,18 +28,6 @@ export function SubagentPulse() {
|
|
|
28
28
|
const label = overA2A
|
|
29
29
|
? `${name} is working over A2A…`
|
|
30
30
|
: `${name} is working…`;
|
|
31
|
-
return (_jsxs(_Fragment, { children: [_jsx("style", { children: KEYFRAMES }), _jsx(Tooltip, { text: label, direction: "n", children: _jsx(Box, { as: "button", type: "button", "aria-label": label, "data-subagent-pulse": name,
|
|
32
|
-
display: 'inline-flex',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
justifyContent: 'center',
|
|
35
|
-
width: 28,
|
|
36
|
-
height: 28,
|
|
37
|
-
p: 0,
|
|
38
|
-
border: 0,
|
|
39
|
-
bg: 'transparent',
|
|
40
|
-
color: 'accent.fg',
|
|
41
|
-
cursor: 'default',
|
|
42
|
-
animation: `${PULSE_ANIMATION} 1.4s ease-in-out infinite`,
|
|
43
|
-
}, children: _jsx(Icon, { size: 16 }) }) })] }));
|
|
31
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { children: KEYFRAMES }), _jsx(Tooltip, { text: label, direction: "n", children: _jsx(Box, { as: "button", type: "button", "aria-label": label, "data-subagent-pulse": name, display: "inline-flex", alignItems: "center", justifyContent: "center", width: 28, height: 28, p: 0, border: 0, bg: "transparent", color: "accent.fg", cursor: "default", animation: `${PULSE_ANIMATION} 1.4s ease-in-out infinite`, children: _jsx(Icon, { size: 16 }) }) })] }));
|
|
44
32
|
}
|
|
45
33
|
export default SubagentPulse;
|
|
@@ -13,50 +13,16 @@ export function WindowFrame({ children, title, height, slotProps = {}, }) {
|
|
|
13
13
|
* actions and fills them in when the workspace registers one.
|
|
14
14
|
*/
|
|
15
15
|
const actions = useOptionalSlotComponents(WINDOW_ACTIONS_SLOT);
|
|
16
|
-
return (_jsxs(Box, {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
borderColor: 'border.default',
|
|
27
|
-
bg: 'canvas.default',
|
|
28
|
-
// Lifted off the field, so the workspace reads as a thing sitting on
|
|
29
|
-
// the page rather than a hole cut into it.
|
|
30
|
-
boxShadow: '0 24px 60px -28px rgba(0, 0, 0, 0.55)',
|
|
31
|
-
}, children: [_jsxs(Box, { sx: {
|
|
32
|
-
display: 'flex',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
gap: 2,
|
|
35
|
-
px: 3,
|
|
36
|
-
py: 2,
|
|
37
|
-
borderBottom: '1px solid',
|
|
38
|
-
borderColor: 'border.default',
|
|
39
|
-
bg: 'canvas.subtle',
|
|
40
|
-
// The bar may be the page's first line of type as well as its
|
|
41
|
-
// chrome, so it takes a second row on a narrow screen rather than
|
|
42
|
-
// shedding its actions off the edge.
|
|
43
|
-
flexWrap: 'wrap',
|
|
44
|
-
rowGap: 2,
|
|
45
|
-
// Never squeezed by the body beside it.
|
|
46
|
-
flex: '0 0 auto',
|
|
47
|
-
}, children: [_jsx(Box, { sx: {
|
|
48
|
-
display: 'flex',
|
|
49
|
-
alignItems: 'center',
|
|
50
|
-
gap: '6px',
|
|
51
|
-
mr: 1,
|
|
52
|
-
flexShrink: 0,
|
|
53
|
-
}, children: _jsx(ReactorSlot, { slot: WINDOW_CONTROLS_SLOT, props: slotProps }) }), _jsx(Box, { sx: { minWidth: 0, flex: '1 1 auto' }, children: title }), actions.length > 0 ? (_jsx(Box, { sx: {
|
|
54
|
-
display: 'flex',
|
|
55
|
-
alignItems: 'center',
|
|
56
|
-
gap: 2,
|
|
57
|
-
flexShrink: 0,
|
|
58
|
-
ml: 'auto',
|
|
59
|
-
}, children: _jsx(ReactorSlot, { slot: WINDOW_ACTIONS_SLOT, props: slotProps }) })) : null] }), _jsx(Box, { sx: height === undefined
|
|
16
|
+
return (_jsxs(Box, { position: "relative", borderRadius: "14px", overflow: "hidden", border: "1px solid", borderColor: "border.default", bg: "canvas.default",
|
|
17
|
+
// Lifted off the field, so the workspace reads as a thing sitting on
|
|
18
|
+
// the page rather than a hole cut into it.
|
|
19
|
+
boxShadow: "0 24px 60px -28px rgba(0, 0, 0, 0.55)", height: height === undefined ? '100%' : undefined, display: height === undefined ? 'flex' : undefined, flexDirection: height === undefined ? 'column' : undefined, children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, px: 3, py: 2, borderBottom: "1px solid", borderColor: "border.default", bg: "canvas.subtle",
|
|
20
|
+
// The bar may be the page's first line of type as well as its
|
|
21
|
+
// chrome, so it takes a second row on a narrow screen rather than
|
|
22
|
+
// shedding its actions off the edge.
|
|
23
|
+
flexWrap: "wrap", rowGap: 2,
|
|
24
|
+
// Never squeezed by the body beside it.
|
|
25
|
+
flex: "0 0 auto", children: [_jsx(Box, { display: "flex", alignItems: "center", gap: "6px", mr: 1, flexShrink: 0, children: _jsx(ReactorSlot, { slot: WINDOW_CONTROLS_SLOT, props: slotProps }) }), _jsx(Box, { minWidth: 0, flex: "1 1 auto", children: title }), actions.length > 0 ? (_jsx(Box, { display: "flex", alignItems: "center", gap: 2, flexShrink: 0, ml: "auto", children: _jsx(ReactorSlot, { slot: WINDOW_ACTIONS_SLOT, props: slotProps }) })) : null] }), _jsx(Box, { sx: height === undefined
|
|
60
26
|
? { flex: '1 1 auto', minHeight: 0 }
|
|
61
27
|
: { height, minHeight: 0 }, children: children })] }));
|
|
62
28
|
}
|
|
@@ -48,7 +48,7 @@ export const WINDOW_FRAME_PLUGIN_NAME = '@datalayer/loop-plugin-window-frame';
|
|
|
48
48
|
* controls can switch this plugin off and fill the slot itself.
|
|
49
49
|
*/
|
|
50
50
|
function WindowControls() {
|
|
51
|
-
return (_jsx(_Fragment, { children: ['danger.emphasis', 'attention.emphasis', 'success.emphasis'].map(token => (_jsx(Box, {
|
|
51
|
+
return (_jsx(_Fragment, { children: ['danger.emphasis', 'attention.emphasis', 'success.emphasis'].map(token => (_jsx(Box, { width: 10, height: 10, borderRadius: "50%", bg: token }, token))) }));
|
|
52
52
|
}
|
|
53
53
|
export const WindowFramePlugin = definePlugin({
|
|
54
54
|
name: WINDOW_FRAME_PLUGIN_NAME,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
|
-
import { Box } from '@primer
|
|
4
|
+
import { Box } from '@datalayer/primer-addons';
|
|
5
5
|
import { buildReactorFromPlugins, onView, } from '@datalayer/reactor';
|
|
6
6
|
import { ReactorSlot, ReactorViewHost, useContributions, useReactorEvent, useSlotComponents, useReactor, } from '@datalayer/reactor/react';
|
|
7
7
|
import { LoopCommand, LoopSlots, LoopViewType, canOpenView, createPromptChannel, parseCommand, loopSurfaceId, } from '../core';
|
|
@@ -168,82 +168,39 @@ function WorkspaceBody({ serverUrl, agentId: initialAgentId, conversationId, mod
|
|
|
168
168
|
through the context: the plugin needs a DOM node and nothing else, and
|
|
169
169
|
the shell should not have to publish one to be found.
|
|
170
170
|
*/
|
|
171
|
-
, { "data-loop-workspace": "",
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
two lines tall is legible, a compressed one is not.
|
|
204
|
-
*/
|
|
205
|
-
flexWrap: 'wrap',
|
|
206
|
-
gap: 2,
|
|
207
|
-
px: compact ? 2 : 3,
|
|
208
|
-
py: 2,
|
|
209
|
-
borderBottom: '1px solid',
|
|
210
|
-
borderColor: 'border.default',
|
|
211
|
-
flex: '0 0 auto',
|
|
212
|
-
}, children: headerControls })) : null, _jsxs(Box, { sx: { flex: '1 1 auto', minHeight: 0, display: 'flex' }, children: [_jsx(Box, { sx: {
|
|
213
|
-
flex: '1 1 auto',
|
|
214
|
-
minWidth: 0,
|
|
215
|
-
minHeight: 0,
|
|
216
|
-
position: 'relative',
|
|
217
|
-
}, children: _jsx(ReactorViewHost, { point: LoopViewType, active: effectiveViewType, props: { viewType: effectiveViewType, workspace }, fallback: _jsx(Centered, { children: "Loading\u2026" }), empty: _jsx(Centered, { children: "No view is available yet." }), errorFallback: error => (_jsxs(Centered, { children: ["This view failed to load: ", error.message] })) }) }), sidebar.length > 0 && sidebarRail && !compact ? (_jsx(SidebarRail, { components: sidebar, props: { workspace }, width: SIDEBAR_WIDTH })) : sidebar.length > 0 ? (_jsx(Box, { as: "aside", sx: {
|
|
218
|
-
flex: '0 0 auto',
|
|
219
|
-
// Wide enough for a plugin's name, its description and a switch
|
|
220
|
-
// on one line. The panel truncates to the same number, and takes
|
|
221
|
-
// it from `SIDEBAR_WIDTH` so the two cannot drift.
|
|
222
|
-
width: compact ? '100%' : `${SIDEBAR_WIDTH}px`,
|
|
223
|
-
minWidth: 0,
|
|
224
|
-
// On the trailing edge: the work is what a person reads first,
|
|
225
|
-
// and the switches belong beside it rather than in front of it.
|
|
226
|
-
borderLeft: compact ? 'none' : '1px solid',
|
|
227
|
-
borderTop: compact ? '1px solid' : 'none',
|
|
228
|
-
borderColor: 'border.default',
|
|
229
|
-
bg: 'canvas.subtle',
|
|
230
|
-
overflowY: 'auto',
|
|
231
|
-
// The shell's chrome, not the plugins': a contributed panel
|
|
232
|
-
// should not have to guess how far its host keeps things from
|
|
233
|
-
// the edge, and two of them would guess differently.
|
|
234
|
-
px: 3,
|
|
235
|
-
py: 3,
|
|
236
|
-
}, children: _jsx(ReactorSlot, { slot: LoopSlots.sidebar, props: { workspace } }) })) : null] }), _jsxs(Box, { sx: { flex: '0 0 auto' }, children: [_jsx(ReactorSlot, { slot: LoopSlots.footer, props: { workspace } }), _jsx(ReactorSlot, { slot: LoopSlots.status, props: { workspace } })] }), _jsx(ReactorSlot, { slot: LoopSlots.root, props: { workspace } })] }));
|
|
171
|
+
, { "data-loop-workspace": "", display: "flex", flexDirection: "column", height: "100%", minHeight: 0,
|
|
172
|
+
// The containing block for anything in the root slot that positions
|
|
173
|
+
// itself absolutely — the floating prompt does. Without this it would
|
|
174
|
+
// resolve against whatever ancestor happens to be positioned, and
|
|
175
|
+
// float over the host's page instead of over the workspace.
|
|
176
|
+
position: "relative", bg: "canvas.default", color: "fg.default", children: [showHeader && headerContainer
|
|
177
|
+
? createPortal(_jsx(Box, { display: "flex", alignItems: "center", flexWrap: "wrap", gap: 2, children: headerControls }), headerContainer)
|
|
178
|
+
: null, showHeader && headerContainer === undefined ? (_jsx(Box, { as: "header", display: "flex", alignItems: "center",
|
|
179
|
+
// In a column there is no room for a row: the header wraps rather
|
|
180
|
+
// than pushing the model chip off the edge.
|
|
181
|
+
justifyContent: compact ? 'flex-start' : 'space-between',
|
|
182
|
+
/*
|
|
183
|
+
Allowed to wrap at any width.
|
|
184
|
+
|
|
185
|
+
`nowrap` meant the row absorbed whatever a plugin put in it by
|
|
186
|
+
squeezing everything else — a sandbox failure message, a long
|
|
187
|
+
agent name — instead of taking a second line. The controls stayed
|
|
188
|
+
on one row and got narrower, which is the wrong trade: a header
|
|
189
|
+
two lines tall is legible, a compressed one is not.
|
|
190
|
+
*/
|
|
191
|
+
flexWrap: "wrap", gap: 2, px: compact ? 2 : 3, py: 2, borderBottom: "1px solid", borderColor: "border.default", flex: "0 0 auto", children: headerControls })) : null, _jsxs(Box, { flex: "1 1 auto", minHeight: 0, display: "flex", children: [_jsx(Box, { flex: "1 1 auto", minWidth: 0, minHeight: 0, position: "relative", children: _jsx(ReactorViewHost, { point: LoopViewType, active: effectiveViewType, props: { viewType: effectiveViewType, workspace }, fallback: _jsx(Centered, { children: "Loading\u2026" }), empty: _jsx(Centered, { children: "No view is available yet." }), errorFallback: error => (_jsxs(Centered, { children: ["This view failed to load: ", error.message] })) }) }), sidebar.length > 0 && sidebarRail && !compact ? (_jsx(SidebarRail, { components: sidebar, props: { workspace }, width: SIDEBAR_WIDTH })) : sidebar.length > 0 ? (_jsx(Box, { as: "aside", flex: "0 0 auto",
|
|
192
|
+
// Wide enough for a plugin's name, its description and a switch
|
|
193
|
+
// on one line. The panel truncates to the same number, and takes
|
|
194
|
+
// it from `SIDEBAR_WIDTH` so the two cannot drift.
|
|
195
|
+
width: compact ? '100%' : `${SIDEBAR_WIDTH}px`, minWidth: 0,
|
|
196
|
+
// On the trailing edge: the work is what a person reads first,
|
|
197
|
+
// and the switches belong beside it rather than in front of it.
|
|
198
|
+
borderLeft: compact ? 'none' : '1px solid', borderTop: compact ? '1px solid' : 'none', borderColor: "border.default", bg: "canvas.subtle", overflowY: "auto",
|
|
199
|
+
// The shell's chrome, not the plugins': a contributed panel
|
|
200
|
+
// should not have to guess how far its host keeps things from
|
|
201
|
+
// the edge, and two of them would guess differently.
|
|
202
|
+
px: 3, py: 3, children: _jsx(ReactorSlot, { slot: LoopSlots.sidebar, props: { workspace } }) })) : null] }), _jsxs(Box, { flex: "0 0 auto", children: [_jsx(ReactorSlot, { slot: LoopSlots.footer, props: { workspace } }), _jsx(ReactorSlot, { slot: LoopSlots.status, props: { workspace } })] }), _jsx(ReactorSlot, { slot: LoopSlots.root, props: { workspace } })] }));
|
|
237
203
|
}
|
|
238
204
|
function Centered({ children }) {
|
|
239
|
-
return (_jsx(Box, {
|
|
240
|
-
height: '100%',
|
|
241
|
-
display: 'flex',
|
|
242
|
-
alignItems: 'center',
|
|
243
|
-
justifyContent: 'center',
|
|
244
|
-
color: 'fg.muted',
|
|
245
|
-
fontSize: 1,
|
|
246
|
-
px: 3,
|
|
247
|
-
textAlign: 'center',
|
|
248
|
-
}, children: children }));
|
|
205
|
+
return (_jsx(Box, { height: "100%", display: "flex", alignItems: "center", justifyContent: "center", color: "fg.muted", fontSize: 1, px: 3, textAlign: "center", children: children }));
|
|
249
206
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useSyncExternalStore } from 'react';
|
|
3
|
-
import { Box
|
|
3
|
+
import { Box } from '@datalayer/primer-addons';
|
|
4
|
+
import { Text } from '@primer/react';
|
|
4
5
|
import { useReactorPlatform } from '@datalayer/reactor/react';
|
|
5
6
|
/** Trim the package scope so the list reads as names rather than paths. */
|
|
6
7
|
function shortName(name) {
|
|
@@ -21,21 +22,9 @@ export function PluginToggles({ locked = [], title = 'Plugins', }) {
|
|
|
21
22
|
reactor.disable(name);
|
|
22
23
|
}
|
|
23
24
|
}, [reactor]);
|
|
24
|
-
return (_jsxs(Box, { sx: {
|
|
25
|
-
p: 3,
|
|
26
|
-
borderBottom: '1px solid',
|
|
27
|
-
borderColor: 'border.default',
|
|
28
|
-
bg: 'canvas.subtle',
|
|
29
|
-
}, children: [_jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: title }), _jsx(Box, { sx: { display: 'flex', flexWrap: 'wrap', gap: 3, mt: 2 }, children: reactor.listPlugins().map(name => {
|
|
25
|
+
return (_jsxs(Box, { p: 3, borderBottom: "1px solid", borderColor: "border.default", bg: "canvas.subtle", children: [_jsx(Text, { sx: { fontSize: 0, fontWeight: 'bold', color: 'fg.muted' }, children: title }), _jsx(Box, { display: "flex", flexWrap: "wrap", gap: 3, mt: 2, children: reactor.listPlugins().map(name => {
|
|
30
26
|
const isLocked = locked.includes(name);
|
|
31
|
-
return (_jsxs(Box, { as: "label",
|
|
32
|
-
display: 'inline-flex',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
gap: 1,
|
|
35
|
-
fontSize: 1,
|
|
36
|
-
cursor: isLocked ? 'not-allowed' : 'pointer',
|
|
37
|
-
opacity: isLocked ? 0.6 : 1,
|
|
38
|
-
}, children: [_jsx("input", { type: "checkbox", checked: reactor.isEnabled(name), disabled: isLocked, onChange: event => toggle(name, event.target.checked) }), shortName(name)] }, name));
|
|
27
|
+
return (_jsxs(Box, { as: "label", display: "inline-flex", alignItems: "center", gap: 1, fontSize: 1, cursor: isLocked ? 'not-allowed' : 'pointer', opacity: isLocked ? 0.6 : 1, children: [_jsx("input", { type: "checkbox", checked: reactor.isEnabled(name), disabled: isLocked, onChange: event => toggle(name, event.target.checked) }), shortName(name)] }, name));
|
|
39
28
|
}) })] }));
|
|
40
29
|
}
|
|
41
30
|
export default PluginToggles;
|
|
@@ -23,51 +23,19 @@ export function SidebarRail({ components, props, width, }) {
|
|
|
23
23
|
const [chosen, setChosen] = useState(items[0]?.id ?? null);
|
|
24
24
|
// A panel that left the slot is no longer chosen.
|
|
25
25
|
const open = items.some(item => item.id === chosen) ? chosen : null;
|
|
26
|
-
return (_jsxs(Box, { as: "aside", "data-loop-rail-sidebar": "",
|
|
27
|
-
display: open ? 'block' : 'none',
|
|
28
|
-
width: `${width}px`,
|
|
29
|
-
minWidth: 0,
|
|
30
|
-
borderLeft: 'var(--theme-hairline, 1px) solid',
|
|
31
|
-
borderColor: 'border.default',
|
|
32
|
-
overflowY: 'auto',
|
|
33
|
-
px: 3,
|
|
34
|
-
py: 3,
|
|
35
|
-
}, children: components.map(component => {
|
|
26
|
+
return (_jsxs(Box, { as: "aside", "data-loop-rail-sidebar": "", flex: "0 0 auto", display: "flex", minHeight: 0, children: [_jsx(Box, { "data-loop-rail-panel": open ?? undefined, display: open ? 'block' : 'none', width: `${width}px`, minWidth: 0, borderLeft: "var(--theme-hairline, 1px) solid", borderColor: "border.default", overflowY: "auto", px: 3, py: 3, children: components.map(component => {
|
|
36
27
|
const { Component } = component;
|
|
37
28
|
const shown = component.id === open;
|
|
38
29
|
return (_jsx(Box, { id: `loop-rail-panel-${component.id}`, role: "region", "aria-label": railItemsOf([component])[0].label, hidden: !shown, sx: shown ? paneOpening('right') : undefined, children: _jsx(Component, { ...props }) }, component.id));
|
|
39
|
-
}) }), _jsx(Box, { as: "nav", "aria-label": "Panels",
|
|
40
|
-
width: `${RAIL_WIDTH}px`,
|
|
41
|
-
flex: `0 0 ${RAIL_WIDTH}px`,
|
|
42
|
-
display: 'flex',
|
|
43
|
-
flexDirection: 'column',
|
|
44
|
-
alignItems: 'center',
|
|
45
|
-
gap: 1,
|
|
46
|
-
py: 2,
|
|
47
|
-
borderLeft: 'var(--theme-hairline, 1px) solid',
|
|
48
|
-
borderColor: 'border.default',
|
|
49
|
-
}, children: items.map(item => {
|
|
30
|
+
}) }), _jsx(Box, { as: "nav", "aria-label": "Panels", width: `${RAIL_WIDTH}px`, flex: `0 0 ${RAIL_WIDTH}px`, display: "flex", flexDirection: "column", alignItems: "center", gap: 1, py: 2, borderLeft: "var(--theme-hairline, 1px) solid", borderColor: "border.default", children: items.map(item => {
|
|
50
31
|
const Icon = item.icon;
|
|
51
32
|
const active = item.id === open;
|
|
52
|
-
return (_jsx(Box, { as: "button", type: "button", "data-loop-rail-item": item.id, "aria-label": item.label, title: item.label, "aria-pressed": active, "aria-controls": `loop-rail-panel-${item.id}`, onClick: () => setChosen(railChoiceAfter(open, item.id)),
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
p: 0,
|
|
59
|
-
border: 'none',
|
|
60
|
-
borderRadius: 2,
|
|
61
|
-
cursor: 'pointer',
|
|
62
|
-
// One weight, no colour: the ink, quieter when not chosen.
|
|
63
|
-
color: active ? 'fg.default' : 'fg.muted',
|
|
64
|
-
bg: active ? 'neutral.muted' : 'transparent',
|
|
65
|
-
'&:hover': { color: 'fg.default', bg: 'neutral.subtle' },
|
|
66
|
-
'&:focus-visible': {
|
|
67
|
-
outline: '2px solid',
|
|
68
|
-
outlineColor: 'var(--focus-outlineColor, #0969da)',
|
|
69
|
-
outlineOffset: '1px',
|
|
70
|
-
},
|
|
33
|
+
return (_jsx(Box, { as: "button", type: "button", "data-loop-rail-item": item.id, "aria-label": item.label, title: item.label, "aria-pressed": active, "aria-controls": `loop-rail-panel-${item.id}`, onClick: () => setChosen(railChoiceAfter(open, item.id)), width: 32, height: 32, display: "inline-flex", alignItems: "center", justifyContent: "center", p: 0, border: "none", borderRadius: 2, cursor: "pointer",
|
|
34
|
+
// One weight, no colour: the ink, quieter when not chosen.
|
|
35
|
+
color: active ? 'fg.default' : 'fg.muted', bg: active ? 'neutral.muted' : 'transparent', hover: { color: 'fg.default', bg: 'neutral.subtle' }, focusVisible: {
|
|
36
|
+
outline: '2px solid',
|
|
37
|
+
outlineColor: 'var(--focus-outlineColor, #0969da)',
|
|
38
|
+
outlineOffset: '1px',
|
|
71
39
|
}, children: _jsx(Icon, { size: 16 }) }, item.id));
|
|
72
40
|
}) })] }));
|
|
73
41
|
}
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box
|
|
2
|
+
import { Box } from '@datalayer/primer-addons';
|
|
3
|
+
import { Tooltip } from '@primer/react';
|
|
3
4
|
import { canOpenView, } from '../core';
|
|
4
5
|
export function ViewSwitcher({ views, workspace, compact = false, }) {
|
|
5
6
|
// One choice is not a choice.
|
|
6
7
|
if (views.length < 2) {
|
|
7
8
|
return null;
|
|
8
9
|
}
|
|
9
|
-
return (_jsx(Box, { role: "tablist", "aria-label": "Workspace views",
|
|
10
|
-
display: 'inline-flex',
|
|
11
|
-
alignItems: 'center',
|
|
12
|
-
bg: 'neutral.muted',
|
|
13
|
-
borderRadius: '6px',
|
|
14
|
-
p: '2px',
|
|
15
|
-
gap: '1px',
|
|
16
|
-
}, children: views.map(entry => {
|
|
10
|
+
return (_jsx(Box, { role: "tablist", "aria-label": "Workspace views", display: "inline-flex", alignItems: "center", bg: "neutral.muted", borderRadius: "6px", p: "2px", gap: "1px", children: views.map(entry => {
|
|
17
11
|
const view = entry.value;
|
|
18
12
|
const open = canOpenView(view, workspace);
|
|
19
13
|
const active = workspace.activeViewType === view.viewType;
|
|
@@ -24,20 +18,6 @@ export function ViewSwitcher({ views, workspace, compact = false, }) {
|
|
|
24
18
|
const label = open
|
|
25
19
|
? view.title
|
|
26
20
|
: `${view.title} — ${view.unavailableReason?.(workspace) ?? 'unavailable'}`;
|
|
27
|
-
return (_jsx(Tooltip, { text: label, direction: "n", children: _jsxs(Box, { as: "button", role: "tab", "aria-selected": active, "aria-disabled": !open, onClick: () => open && workspace.setActiveViewType(view.viewType),
|
|
28
|
-
display: 'inline-flex',
|
|
29
|
-
alignItems: 'center',
|
|
30
|
-
gap: 1,
|
|
31
|
-
border: 'none',
|
|
32
|
-
borderRadius: '5px',
|
|
33
|
-
px: 2,
|
|
34
|
-
py: '4px',
|
|
35
|
-
fontSize: 0,
|
|
36
|
-
cursor: open ? 'pointer' : 'not-allowed',
|
|
37
|
-
opacity: open ? 1 : 0.5,
|
|
38
|
-
bg: active ? 'canvas.default' : 'transparent',
|
|
39
|
-
color: active ? 'fg.default' : 'fg.muted',
|
|
40
|
-
boxShadow: active ? 'shadow.small' : 'none',
|
|
41
|
-
}, children: [Icon ? _jsx(Icon, { size: 14 }) : null, compact && Icon ? null : view.title] }) }, view.viewType));
|
|
21
|
+
return (_jsx(Tooltip, { text: label, direction: "n", children: _jsxs(Box, { as: "button", role: "tab", "aria-selected": active, "aria-disabled": !open, onClick: () => open && workspace.setActiveViewType(view.viewType), display: "inline-flex", alignItems: "center", gap: 1, border: "none", borderRadius: "5px", px: 2, py: "4px", fontSize: 0, cursor: open ? 'pointer' : 'not-allowed', opacity: open ? 1 : 0.5, bg: active ? 'canvas.default' : 'transparent', color: active ? 'fg.default' : 'fg.muted', boxShadow: active ? 'shadow.small' : 'none', children: [Icon ? _jsx(Icon, { size: 14 }) : null, compact && Icon ? null : view.title] }) }, view.viewType));
|
|
42
22
|
}) }));
|
|
43
23
|
}
|
package/lib/loop-main.js
CHANGED
|
@@ -31,8 +31,7 @@ if (globals['__webpack_public_path__'] === undefined) {
|
|
|
31
31
|
import { StrictMode, useEffect, useState } from 'react';
|
|
32
32
|
import { createRoot } from 'react-dom/client';
|
|
33
33
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
34
|
-
import { Box } from '@primer
|
|
35
|
-
import { DatalayerThemeProvider, setupPrimerPortals, themeConfigs, useSystemColorMode, useThemeStore, } from '@datalayer/primer-addons';
|
|
34
|
+
import { Box, DatalayerThemeProvider, setupPrimerPortals, themeConfigs, useSystemColorMode, useThemeStore, } from '@datalayer/primer-addons';
|
|
36
35
|
import { configurePlugin } from '@datalayer/reactor';
|
|
37
36
|
import { LoopWorkspace } from './loop/shell/LoopWorkspace';
|
|
38
37
|
import { ChatPlugin } from './loop/plugins/chat';
|
|
@@ -113,7 +112,7 @@ function LoopPage() {
|
|
|
113
112
|
const serverUrl = window.location.origin;
|
|
114
113
|
void resolveSession(serverUrl).then(setSession);
|
|
115
114
|
}, []);
|
|
116
|
-
return (_jsx(DatalayerThemeProvider, { colorMode: resolvedMode, theme: themeConfig.primerTheme, themeStyles: themeConfig.themeStyles, children: _jsx(QueryClientProvider, { client: internalQueryClient, children: _jsx(Box, {
|
|
115
|
+
return (_jsx(DatalayerThemeProvider, { colorMode: resolvedMode, theme: themeConfig.primerTheme, themeStyles: themeConfig.themeStyles, children: _jsx(QueryClientProvider, { client: internalQueryClient, children: _jsx(Box, { height: "100vh", overflow: "hidden", children: session ? (_jsx(LoopWorkspace, { serverUrl: session.serverUrl, agentId: session.agentId, conversationId: session.conversationId, model: session.model, sandbox: session.sandbox, initialViewType: session.view,
|
|
117
116
|
// The notebook and document plugins depend on the sandbox, so
|
|
118
117
|
// the reactor pulls it in; it is named here only to be told which
|
|
119
118
|
// server it talks to.
|