@datalayer/agent-runtimes 1.3.10 → 1.3.11
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/api/runtimes/environments.d.ts +22 -1
- package/lib/api/runtimes/environments.js +31 -0
- package/lib/chat/ChatFloating.d.ts +8 -1
- package/lib/chat/ChatFloating.js +5 -2
- package/lib/chat/display/ButtonGlow.d.ts +9 -0
- package/lib/chat/display/ButtonGlow.js +60 -0
- package/lib/chat/display/EmptyState.js +4 -1
- package/lib/chat/header/ChatHeaderBase.js +4 -56
- package/lib/chat/header/ChatViewModeToggle.d.ts +29 -0
- package/lib/chat/header/ChatViewModeToggle.js +55 -0
- package/lib/chat/index.d.ts +1 -0
- package/lib/chat/index.js +1 -0
- package/lib/components/code-sandboxes/CodeSandboxLauncher.d.ts +8 -0
- package/lib/components/code-sandboxes/CodeSandboxLauncher.js +54 -5
- package/lib/components/code-sandboxes/codeSandboxEnvironments.d.ts +12 -1
- package/lib/components/code-sandboxes/codeSandboxEnvironments.js +38 -1
- package/lib/components/icons/ArtifactIcon.js +2 -1
- package/lib/examples/DecksAgent.d.ts +1 -1
- package/lib/examples/DecksAgent.js +1 -1
- package/lib/loop/core/index.d.ts +11 -2
- package/lib/loop/embed/LoopEmbed.js +6 -0
- package/lib/loop/plugins/chat/ChatView.js +14 -5
- package/lib/loop/plugins/page-layout/index.d.ts +36 -0
- package/lib/loop/plugins/page-layout/index.js +87 -7
- package/lib/loop/presets.d.ts +14 -0
- package/lib/loop/presets.js +3 -1
- package/lib/models/Deck.d.ts +14 -0
- package/lib/models/Deck.js +5 -0
- package/lib/models/Environment.d.ts +117 -0
- package/lib/models/ItemType.d.ts +1 -1
- package/lib/models/Runtime.d.ts +6 -0
- package/lib/models/SpaceItem.d.ts +2 -1
- package/lib/models/environments.generated.d.ts +29 -1
- package/lib/models/environments.generated.js +1 -1
- package/lib/models/index.d.ts +1 -0
- package/lib/models/index.js +1 -0
- package/lib/protocols/BrowserAgentAdapter.d.ts +9 -1
- package/lib/protocols/BrowserAgentAdapter.js +11 -4
- package/lib/runtimes/actions.d.ts +5 -0
- package/lib/runtimes/actions.js +19 -0
- package/lib/specs/agents/agents.d.ts +2 -1
- package/lib/specs/agents/agents.js +314 -130
- package/lib/specs/frontendTools.d.ts +1 -0
- package/lib/specs/frontendTools.js +31 -0
- package/lib/specs/mcpServers.js +13 -13
- package/lib/specs/models.js +4 -4
- package/lib/specs/outputs.js +9 -0
- package/lib/specs/skills.js +7 -7
- package/lib/specs/teams/teams.js +1 -1
- package/lib/types/outputs.d.ts +2 -0
- package/package.json +1 -1
- package/scripts/codegen/generate_mcp_servers.py +2 -2
- package/scripts/codegen/generate_outputs.py +2 -0
- package/scripts/codegen/generate_skills.py +2 -2
- package/scripts/codegen/__pycache__/compose.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Reactor plugin with a Python half of its own, and here it is mounted into
|
|
6
6
|
* an agent workspace — its list in the sidebar, its view as an editor beside
|
|
7
7
|
* the conversation, its commands in the palette and in a menu on the
|
|
8
|
-
* composer, and its tools in the agent's hands. `
|
|
8
|
+
* composer, and its tools in the agent's hands. `example-decks` writes a deck
|
|
9
9
|
* as data, saves it, opens it, and steps through it while you talk.
|
|
10
10
|
*
|
|
11
11
|
* Everything runs in the browser: the agent on the Vercel AI harness, the
|
|
@@ -11,7 +11,7 @@ registerDecks(exampleDecks);
|
|
|
11
11
|
// Module-level, so the embed builds its reactor once rather than on every
|
|
12
12
|
// render of this component.
|
|
13
13
|
const DECK_PLUGINS = [LoopDecksPlugin, DeckViewPlugin];
|
|
14
|
-
const DecksAgent = () => (_jsx(ThemedProvider, { children: _jsx(Box, { sx: { height: '100vh', minHeight: 0 }, children: _jsx(LoopEmbed, { target: "browser", agentId: "
|
|
14
|
+
const DecksAgent = () => (_jsx(ThemedProvider, { children: _jsx(Box, { sx: { height: '100vh', minHeight: 0 }, children: _jsx(LoopEmbed, { target: "browser", agentId: "example-decks",
|
|
15
15
|
/* The deck open beside the chat from the first frame. */
|
|
16
16
|
defaultEditor: "deck",
|
|
17
17
|
/* The header carries the editor choice — deck, notebook, document, or
|
package/lib/loop/core/index.d.ts
CHANGED
|
@@ -824,14 +824,23 @@ export type ChatLayoutContribution = {
|
|
|
824
824
|
/**
|
|
825
825
|
* How this layout wants the composer built.
|
|
826
826
|
*
|
|
827
|
-
* `floating-top`
|
|
827
|
+
* `floating-top` and `floating-bottom` are a floating card anchored to
|
|
828
|
+
* that edge of the layout rather than
|
|
828
829
|
* the bottom — a command line over the document, sized by the card.
|
|
829
830
|
* `docked-top` is that same command line standing in the flow instead: the
|
|
830
831
|
* layout gives it a mount point and the composer fills it, so its width is
|
|
831
832
|
* the layout's to decide and the page below starts under it rather than
|
|
832
833
|
* behind it.
|
|
833
834
|
*/
|
|
834
|
-
prompt?: 'docked' | 'floating' | 'floating-top' | 'docked-top';
|
|
835
|
+
prompt?: 'docked' | 'floating' | 'floating-top' | 'floating-bottom' | 'docked-top';
|
|
836
|
+
/**
|
|
837
|
+
* The same, live, for a layout whose stance changes while it is on
|
|
838
|
+
* screen — the page layout moves the composer between a floating card
|
|
839
|
+
* and its side panel as the person picks a display mode. Read over
|
|
840
|
+
* `prompt` by the chat view whenever it is given; `prompt` is then only
|
|
841
|
+
* the stance the layout starts in.
|
|
842
|
+
*/
|
|
843
|
+
promptStance?: ReadonlySignal<'docked' | 'floating' | 'floating-top' | 'floating-bottom' | 'docked-top'>;
|
|
835
844
|
};
|
|
836
845
|
export declare const LoopChatLayout: import("@datalayer/reactor").ContributionPoint<ChatLayoutContribution>;
|
|
837
846
|
/**
|
|
@@ -77,6 +77,12 @@ export function LoopEmbed({ agentId = '', showHeader = false, chatHeaderActions,
|
|
|
77
77
|
preset.pageLayoutTurnPanel,
|
|
78
78
|
preset.pageLayoutTurnPanelFooter,
|
|
79
79
|
preset.pageLayoutPrompt,
|
|
80
|
+
preset.pageLayoutPromptAnchor,
|
|
81
|
+
// By its fields: a host that writes the size inline hands over a new
|
|
82
|
+
// object every render, and the reactor must not be rebuilt for that.
|
|
83
|
+
preset.pageLayoutSize?.format,
|
|
84
|
+
preset.pageLayoutSize?.width,
|
|
85
|
+
preset.pageLayoutSize?.height,
|
|
80
86
|
preset.localAgentSpec,
|
|
81
87
|
preset.floatingPrompt,
|
|
82
88
|
preset.editorSelector,
|
|
@@ -4,6 +4,8 @@ import { Box, IconButton, SegmentedControl, Text, Truncate, } from '@primer/reac
|
|
|
4
4
|
import { useColorPalette } from '@datalayer/primer-addons';
|
|
5
5
|
import { ScreenFullIcon, ScreenNormalIcon } from '@primer/octicons-react';
|
|
6
6
|
import { signal } from '@datalayer/reactor';
|
|
7
|
+
/* A signal to read when the layout publishes no live stance: the hook needs one. */
|
|
8
|
+
const NO_STANCE = signal(undefined);
|
|
7
9
|
import { useContributions, useSignalValue, useGate, useReactorPlatform, ReactorLazy, ReactorSlot, useSlotComponents, } from '@datalayer/reactor/react';
|
|
8
10
|
import { ChatBase } from '../../../chat/base/ChatBase';
|
|
9
11
|
import { SUGGESTION_CHIP_WIDTH } from '../../../chat/display/EmptyState';
|
|
@@ -123,6 +125,11 @@ export default function ChatView({ workspace }) {
|
|
|
123
125
|
its own way; first contribution wins. */
|
|
124
126
|
const layoutEntries = useContributions(LoopChatLayout);
|
|
125
127
|
const layout = layoutEntries[0]?.value;
|
|
128
|
+
// The composer's stance: live when the layout publishes one (the page
|
|
129
|
+
// layout, moving the composer as the display mode changes), its starting
|
|
130
|
+
// stance otherwise.
|
|
131
|
+
const liveStance = useSignalValue(layout?.promptStance ?? NO_STANCE);
|
|
132
|
+
const promptStance = liveStance ?? layout?.prompt;
|
|
126
133
|
/* The current turn, kept for whoever shows the conversation without the
|
|
127
134
|
transcript. The chat plugin contributed the feed at build; this view is
|
|
128
135
|
its writer — begin on send, the reply as it arrives, end when it stops. */
|
|
@@ -1183,13 +1190,14 @@ export default function ChatView({ workspace }) {
|
|
|
1183
1190
|
// In a draggable card over the workspace when the host asked for the
|
|
1184
1191
|
// floating placement; the dragging is the prompt's own feature.
|
|
1185
1192
|
placement: floatingPrompt ||
|
|
1186
|
-
|
|
1187
|
-
|
|
1193
|
+
promptStance === 'floating' ||
|
|
1194
|
+
promptStance === 'floating-top' ||
|
|
1195
|
+
promptStance === 'floating-bottom'
|
|
1188
1196
|
? 'floating'
|
|
1189
1197
|
: 'docked',
|
|
1190
1198
|
// Where a floating card starts: the page layout wants it over the top
|
|
1191
1199
|
// of the sheet, like a document's title bar; everyone else, bottom.
|
|
1192
|
-
floatingAnchor:
|
|
1200
|
+
floatingAnchor: promptStance === 'floating-top' ? 'top' : 'bottom',
|
|
1193
1201
|
// The agent is working: `isLoading` disables the editor and turns the
|
|
1194
1202
|
// send button into a stop — the person keeps a way out.
|
|
1195
1203
|
isLoading: busy,
|
|
@@ -1206,8 +1214,9 @@ export default function ChatView({ workspace }) {
|
|
|
1206
1214
|
// Both of the page layout's placements are that bar — one floating over
|
|
1207
1215
|
// the page, one docked above it — so both take the tighter padding.
|
|
1208
1216
|
padding: topPrompt ||
|
|
1209
|
-
|
|
1210
|
-
|
|
1217
|
+
promptStance === 'floating-top' ||
|
|
1218
|
+
promptStance === 'floating-bottom' ||
|
|
1219
|
+
promptStance === 'docked-top'
|
|
1211
1220
|
? 2
|
|
1212
1221
|
: 3,
|
|
1213
1222
|
promptVariant: 'lexical',
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { type PageSize } from '@datalayer/primer-addons/lib/reactor';
|
|
2
|
+
import type { ChatViewMode } from '../../../types/chat';
|
|
1
3
|
import { type TurnPanelFooter } from './TurnPanel';
|
|
2
4
|
export { pageLayoutPanelOpen, pageLayoutSheet, openPagePanel as openConversationPanel, } from '@datalayer/primer-addons/lib/reactor';
|
|
3
5
|
export type { TurnPanelFooter } from './TurnPanel';
|
|
6
|
+
export type { PageSize, PageSizeFormat, } from '@datalayer/primer-addons/lib/reactor';
|
|
4
7
|
export declare const LOOP_PAGE_LAYOUT_PLUGIN_NAME = "@datalayer/loop-plugin-page-layout";
|
|
5
8
|
/** What a host may set on the page layout. */
|
|
6
9
|
export type LoopPageLayoutConfig = {
|
|
@@ -22,6 +25,20 @@ export type LoopPageLayoutConfig = {
|
|
|
22
25
|
* kept clear for it — the document application's title bar, movable.
|
|
23
26
|
*/
|
|
24
27
|
prompt: 'docked' | 'floating';
|
|
28
|
+
/**
|
|
29
|
+
* Which edge of the page a floating composer starts at: `top` (the
|
|
30
|
+
* default), where a document's title bar would be, or `bottom`, where a
|
|
31
|
+
* chat's composer waits. Either way it is dragged from there. Only read
|
|
32
|
+
* with a `floating` prompt.
|
|
33
|
+
*/
|
|
34
|
+
promptAnchor?: 'top' | 'bottom';
|
|
35
|
+
/**
|
|
36
|
+
* The sheet's size: free (the default) at the layout's reading width, or
|
|
37
|
+
* a paper — `{ format: 'letter' }`, `{ format: 'a4' }` — whose width the
|
|
38
|
+
* sheet takes and whose height it is at least, with a free `width` or
|
|
39
|
+
* `height` over either. Omitted: free.
|
|
40
|
+
*/
|
|
41
|
+
pageSize?: PageSize;
|
|
25
42
|
/**
|
|
26
43
|
* What the turn panel draws under the reply.
|
|
27
44
|
*
|
|
@@ -31,5 +48,24 @@ export type LoopPageLayoutConfig = {
|
|
|
31
48
|
*/
|
|
32
49
|
turnPanelFooter: TurnPanelFooter;
|
|
33
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* How the page layout shows the chat, when the composer is the floating
|
|
53
|
+
* card: the card itself over the page (`floating-draggable`, where it
|
|
54
|
+
* starts), or the conversation panel with the composer standing in it —
|
|
55
|
+
* beside the page (`sidebar`), over its right edge at full height
|
|
56
|
+
* (`floating`), or as a window in its corner (`floating-small`). The four
|
|
57
|
+
* modes of the chat header's toggle, which the card carries in its own
|
|
58
|
+
* footer. One signal for the workspace, as `pageLayoutPanelOpen` is: the
|
|
59
|
+
* mode is the person's, not a build's.
|
|
60
|
+
*/
|
|
61
|
+
export declare const pageLayoutChatMode: import("@datalayer/reactor").Signal<ChatViewMode>;
|
|
62
|
+
/** Where a mode puts the composer (the band) and the conversation (the panel). */
|
|
63
|
+
export type PageLayoutChatPlacement = {
|
|
64
|
+
bandMode: 'floating' | 'panel';
|
|
65
|
+
panelMode: 'docked' | 'overlay' | 'popup';
|
|
66
|
+
};
|
|
67
|
+
export declare function pageLayoutForChatMode(mode: ChatViewMode): PageLayoutChatPlacement;
|
|
68
|
+
/** Picks a mode: the layout follows, and so does the composer's stance. */
|
|
69
|
+
export declare function setPageLayoutChatMode(mode: ChatViewMode): void;
|
|
34
70
|
export declare const LoopPageLayoutPlugin: import("@datalayer/reactor").ReactorPlugin<LoopPageLayoutConfig, unknown, unknown>;
|
|
35
71
|
export default LoopPageLayoutPlugin;
|
|
@@ -2,7 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { CommentDiscussionIcon } from '@primer/octicons-react';
|
|
3
3
|
import { definePlugin, signal } from '@datalayer/reactor';
|
|
4
4
|
import { useContributions, useSignalValue } from '@datalayer/reactor/react';
|
|
5
|
-
import { PageLayout, PagePanelToggle, } from '@datalayer/primer-addons/lib/reactor';
|
|
5
|
+
import { PageLayout, PagePanelToggle, openPagePanel, } from '@datalayer/primer-addons/lib/reactor';
|
|
6
|
+
import { ChatViewModeToggle } from '../../../chat/header/ChatViewModeToggle';
|
|
6
7
|
import { LoopChatLayout, LoopChatTurn, LoopPromptPanel, LoopSlots, } from '../../core';
|
|
7
8
|
import { TurnPanel } from './TurnPanel';
|
|
8
9
|
/*
|
|
@@ -14,6 +15,53 @@ export { pageLayoutPanelOpen, pageLayoutSheet, openPagePanel as openConversation
|
|
|
14
15
|
export const LOOP_PAGE_LAYOUT_PLUGIN_NAME = '@datalayer/loop-plugin-page-layout';
|
|
15
16
|
/* A signal to read when no chat contributed a turn: the hook needs one. */
|
|
16
17
|
const NO_TURN = signal({ id: 0, status: 'idle' });
|
|
18
|
+
/**
|
|
19
|
+
* How the page layout shows the chat, when the composer is the floating
|
|
20
|
+
* card: the card itself over the page (`floating-draggable`, where it
|
|
21
|
+
* starts), or the conversation panel with the composer standing in it —
|
|
22
|
+
* beside the page (`sidebar`), over its right edge at full height
|
|
23
|
+
* (`floating`), or as a window in its corner (`floating-small`). The four
|
|
24
|
+
* modes of the chat header's toggle, which the card carries in its own
|
|
25
|
+
* footer. One signal for the workspace, as `pageLayoutPanelOpen` is: the
|
|
26
|
+
* mode is the person's, not a build's.
|
|
27
|
+
*/
|
|
28
|
+
export const pageLayoutChatMode = signal('floating-draggable');
|
|
29
|
+
/** The composer's stance for the chat view, following the mode above. */
|
|
30
|
+
const promptStance = signal('floating-top');
|
|
31
|
+
/*
|
|
32
|
+
* Which edge the card returns to when the mode puts it back over the page:
|
|
33
|
+
* the build's own `promptAnchor`, kept here because the mode is picked
|
|
34
|
+
* through a module-level function, as `pageLayoutChatMode` itself is. One
|
|
35
|
+
* page layout to a page, the assumption that signal already makes.
|
|
36
|
+
*/
|
|
37
|
+
let floatingStance = 'floating-top';
|
|
38
|
+
export function pageLayoutForChatMode(mode) {
|
|
39
|
+
switch (mode) {
|
|
40
|
+
case 'sidebar':
|
|
41
|
+
return { bandMode: 'panel', panelMode: 'docked' };
|
|
42
|
+
case 'floating':
|
|
43
|
+
return { bandMode: 'panel', panelMode: 'overlay' };
|
|
44
|
+
case 'floating-small':
|
|
45
|
+
return { bandMode: 'panel', panelMode: 'popup' };
|
|
46
|
+
default:
|
|
47
|
+
return { bandMode: 'floating', panelMode: 'docked' };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Picks a mode: the layout follows, and so does the composer's stance. */
|
|
51
|
+
export function setPageLayoutChatMode(mode) {
|
|
52
|
+
pageLayoutChatMode.value = mode;
|
|
53
|
+
const { bandMode } = pageLayoutForChatMode(mode);
|
|
54
|
+
promptStance.value = bandMode === 'floating' ? floatingStance : 'docked-top';
|
|
55
|
+
// The composer went into the panel: the panel opens to show it.
|
|
56
|
+
if (bandMode === 'panel') {
|
|
57
|
+
openPagePanel();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** The toggle in the floating composer's footer. */
|
|
61
|
+
function ChatModeAction() {
|
|
62
|
+
const mode = useSignalValue(pageLayoutChatMode);
|
|
63
|
+
return _jsx(ChatViewModeToggle, { value: mode, onChange: setPageLayoutChatMode });
|
|
64
|
+
}
|
|
17
65
|
/**
|
|
18
66
|
* The chat view's parts on the page layout.
|
|
19
67
|
*
|
|
@@ -21,10 +69,16 @@ const NO_TURN = signal({ id: 0, status: 'idle' });
|
|
|
21
69
|
* what the agent is doing — the turn's `activity` — is the line at the top
|
|
22
70
|
* of the sheet, so the change is seen where it happens.
|
|
23
71
|
*/
|
|
24
|
-
function LoopPageLayout({ parts, promptMode, }) {
|
|
72
|
+
function LoopPageLayout({ parts, promptMode, pageSize, }) {
|
|
25
73
|
const turnEntries = useContributions(LoopChatTurn);
|
|
26
74
|
const turn = useSignalValue(turnEntries[0]?.value.turn ?? NO_TURN);
|
|
27
|
-
|
|
75
|
+
const chatMode = useSignalValue(pageLayoutChatMode);
|
|
76
|
+
// The display modes are the floating card's own; a docked composer stays
|
|
77
|
+
// docked above the page, whatever mode was picked elsewhere.
|
|
78
|
+
const placement = promptMode === 'floating'
|
|
79
|
+
? pageLayoutForChatMode(chatMode)
|
|
80
|
+
: { bandMode: 'docked', panelMode: 'docked' };
|
|
81
|
+
return (_jsx(PageLayout, { page: parts.editors, hasPage: parts.hasEditor, panel: parts.transcript, band: parts.prompt, chips: parts.chips, picker: parts.picker, transient: parts.transient, activity: turn.activity, bandMode: placement.bandMode, panelMode: placement.panelMode, pageSize: pageSize }));
|
|
28
82
|
}
|
|
29
83
|
/** The header button that opens and closes the conversation panel. */
|
|
30
84
|
function ConversationToggle() {
|
|
@@ -32,7 +86,13 @@ function ConversationToggle() {
|
|
|
32
86
|
}
|
|
33
87
|
export const LoopPageLayoutPlugin = definePlugin({
|
|
34
88
|
name: LOOP_PAGE_LAYOUT_PLUGIN_NAME,
|
|
35
|
-
config: {
|
|
89
|
+
config: {
|
|
90
|
+
turnPanel: 'below',
|
|
91
|
+
turnPanelFooter: 'full',
|
|
92
|
+
prompt: 'docked',
|
|
93
|
+
promptAnchor: 'top',
|
|
94
|
+
pageSize: undefined,
|
|
95
|
+
},
|
|
36
96
|
displayName: 'Page layout',
|
|
37
97
|
description: 'The editor — or, in the chat view, the conversation — on a centred sheet, the prompt docked above it at the same width or floating over it as a draggable card, the current turn under the prompt, the conversation in a side panel.',
|
|
38
98
|
octicon: 'file',
|
|
@@ -42,15 +102,24 @@ export const LoopPageLayoutPlugin = definePlugin({
|
|
|
42
102
|
The layout, contributed per build because the composer's stance is
|
|
43
103
|
configuration: `docked-top` means the layout owns the composer's width
|
|
44
104
|
— `PageLayout` gives it a mount point the width of the sheet, so the
|
|
45
|
-
prompt and the page read as one column; `floating-top`
|
|
105
|
+
prompt and the page read as one column; `floating-top` and
|
|
106
|
+
`floating-bottom` are the draggable
|
|
46
107
|
card, sized by itself, over a strip of canvas kept clear for it. The
|
|
47
108
|
component closes over the choice once, per build.
|
|
48
109
|
*/
|
|
49
110
|
const promptMode = config.prompt;
|
|
50
|
-
const
|
|
111
|
+
const pageSize = config.pageSize;
|
|
112
|
+
floatingStance =
|
|
113
|
+
config.promptAnchor === 'bottom' ? 'floating-bottom' : 'floating-top';
|
|
114
|
+
if (promptMode === 'floating') {
|
|
115
|
+
promptStance.value = floatingStance;
|
|
116
|
+
}
|
|
117
|
+
const ConfiguredLayout = (parts) => (_jsx(LoopPageLayout, { parts: parts, promptMode: promptMode, pageSize: pageSize }));
|
|
51
118
|
ctx.contribute(LoopChatLayout, {
|
|
52
119
|
id: 'page-layout',
|
|
53
|
-
prompt: promptMode === 'floating' ?
|
|
120
|
+
prompt: promptMode === 'floating' ? floatingStance : 'docked-top',
|
|
121
|
+
// Live only for the card: its display modes move the composer.
|
|
122
|
+
promptStance: promptMode === 'floating' ? promptStance : undefined,
|
|
54
123
|
Component: ConfiguredLayout,
|
|
55
124
|
}, { id: 'page-layout' });
|
|
56
125
|
// The turn panel is configuration-dependent, so it is contributed here
|
|
@@ -73,6 +142,17 @@ export const LoopPageLayoutPlugin = definePlugin({
|
|
|
73
142
|
slot: LoopSlots.header,
|
|
74
143
|
Component: ConversationToggle,
|
|
75
144
|
},
|
|
145
|
+
// The display modes, in the floating card's footer — and only
|
|
146
|
+
// there: a docked composer has none to pick.
|
|
147
|
+
...(promptMode === 'floating'
|
|
148
|
+
? [
|
|
149
|
+
{
|
|
150
|
+
id: 'page-layout-chat-mode',
|
|
151
|
+
slot: LoopSlots.promptAction,
|
|
152
|
+
Component: ChatModeAction,
|
|
153
|
+
},
|
|
154
|
+
]
|
|
155
|
+
: []),
|
|
76
156
|
],
|
|
77
157
|
};
|
|
78
158
|
},
|
package/lib/loop/presets.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { type PluginRef } from '@datalayer/reactor';
|
|
23
23
|
import { type AgentsConfig, type SandboxTarget } from './plugins/agents';
|
|
24
24
|
import { type ChatPluginConfig } from './plugins/chat';
|
|
25
|
+
import { type PageSize } from './plugins/page-layout';
|
|
25
26
|
export type LoopPresetOptions = {
|
|
26
27
|
/** Where the agent runtimes service is. */
|
|
27
28
|
serverUrl?: string;
|
|
@@ -81,6 +82,19 @@ export type LoopPresetOptions = {
|
|
|
81
82
|
* as a draggable card over the top of the canvas.
|
|
82
83
|
*/
|
|
83
84
|
pageLayoutPrompt?: 'docked' | 'floating';
|
|
85
|
+
/**
|
|
86
|
+
* Which edge a floating composer starts at: `top` (the default) or
|
|
87
|
+
* `bottom`. It is dragged from there either way. Only read with
|
|
88
|
+
* `pageLayoutPrompt: 'floating'`.
|
|
89
|
+
*/
|
|
90
|
+
pageLayoutPromptAnchor?: 'top' | 'bottom';
|
|
91
|
+
/**
|
|
92
|
+
* The page layout's sheet: free (the default) at its reading width, or a
|
|
93
|
+
* paper — `{ format: 'letter' }`, `{ format: 'a4' }` — whose width it
|
|
94
|
+
* takes and whose height it is at least; a free `width` or `height` over
|
|
95
|
+
* either. Only read with `pageLayout`.
|
|
96
|
+
*/
|
|
97
|
+
pageLayoutSize?: PageSize;
|
|
84
98
|
/**
|
|
85
99
|
* What the turn panel draws under the reply: the full turn footer
|
|
86
100
|
* (counters, copy, dismiss — the default), `actions` only, or `none`.
|
package/lib/loop/presets.js
CHANGED
|
@@ -51,7 +51,7 @@ import { LoopPageLayoutPlugin } from './plugins/page-layout';
|
|
|
51
51
|
* be installed or signed into, and the switches a demonstration wants are off.
|
|
52
52
|
*/
|
|
53
53
|
export function loopPlugins(options = {}) {
|
|
54
|
-
const { serverUrl, target = 'browser', defaultEditor = 'notebook', showViewSelector = true, hideChatHeader = false, promptPlacement, autoFocusPrompt = true, fullScreenTopOffset = 0, showAgentVariants = false, agentSummary = true, teamId, teamPicker = true, pageLayout = false, pageLayoutTurnPanel = 'below', pageLayoutPrompt = 'docked', pageLayoutTurnPanelFooter = 'full', localAgent, localAgentSpec, floatingPrompt = false, editorSelector = false, editors = true, graph = false, commandPalette = false, pluginsPanel = false, windowFrame = false, firstPromptHook, } = options;
|
|
54
|
+
const { serverUrl, target = 'browser', defaultEditor = 'notebook', showViewSelector = true, hideChatHeader = false, promptPlacement, autoFocusPrompt = true, fullScreenTopOffset = 0, showAgentVariants = false, agentSummary = true, teamId, teamPicker = true, pageLayout = false, pageLayoutTurnPanel = 'below', pageLayoutPrompt = 'docked', pageLayoutPromptAnchor = 'top', pageLayoutSize, pageLayoutTurnPanelFooter = 'full', localAgent, localAgentSpec, floatingPrompt = false, editorSelector = false, editors = true, graph = false, commandPalette = false, pluginsPanel = false, windowFrame = false, firstPromptHook, } = options;
|
|
55
55
|
return [
|
|
56
56
|
// The chat owns the editor beside it, so which one opens is its
|
|
57
57
|
// configuration rather than the workspace's.
|
|
@@ -127,6 +127,8 @@ export function loopPlugins(options = {}) {
|
|
|
127
127
|
turnPanel: pageLayoutTurnPanel,
|
|
128
128
|
turnPanelFooter: pageLayoutTurnPanelFooter,
|
|
129
129
|
prompt: pageLayoutPrompt,
|
|
130
|
+
promptAnchor: pageLayoutPromptAnchor,
|
|
131
|
+
pageSize: pageLayoutSize,
|
|
130
132
|
}),
|
|
131
133
|
]
|
|
132
134
|
: []),
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IItem } from './Item';
|
|
2
|
+
/**
|
|
3
|
+
* A deck: a presentation described as data, on the `@datalayer/decks`
|
|
4
|
+
* engine. `spec` is the deck specification the engine renders — the
|
|
5
|
+
* item's content, the way `nbformat` is a notebook's — present when the
|
|
6
|
+
* item was read on its own and absent in a listing.
|
|
7
|
+
*/
|
|
8
|
+
export type IBaseDeck = IItem & {
|
|
9
|
+
spec?: any;
|
|
10
|
+
};
|
|
11
|
+
export type IDeck = IBaseDeck & {
|
|
12
|
+
type: 'deck';
|
|
13
|
+
};
|
|
14
|
+
export default IDeck;
|
|
@@ -170,6 +170,12 @@ export interface IDatalayerEnvironment {
|
|
|
170
170
|
* from its public page expects to find it.
|
|
171
171
|
*/
|
|
172
172
|
fromLibrary?: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* How a reader is shown an entry whose launch name is not its name: a
|
|
175
|
+
* Library entry is launched by its environment's uid, and shown as the
|
|
176
|
+
* name its owner gave it, `steps-drill`, rather than that uid (E2-19).
|
|
177
|
+
*/
|
|
178
|
+
label?: string;
|
|
173
179
|
}
|
|
174
180
|
/**
|
|
175
181
|
* A refusal, as every registry route answers one (section 10): a code, a
|
|
@@ -358,6 +364,27 @@ export interface IEnvironmentConformanceReport {
|
|
|
358
364
|
passed: boolean;
|
|
359
365
|
checks: IEnvironmentConformanceCheck[];
|
|
360
366
|
}
|
|
367
|
+
/** One step of a build as its workflow ran it (E2-19). */
|
|
368
|
+
export interface IEnvironmentBuildStep {
|
|
369
|
+
name: string;
|
|
370
|
+
status: 'running' | 'succeeded' | 'failed' | 'skipped';
|
|
371
|
+
startedAt?: string;
|
|
372
|
+
finishedAt?: string;
|
|
373
|
+
/** For a failure: its section 10 code. */
|
|
374
|
+
code?: string;
|
|
375
|
+
message?: string;
|
|
376
|
+
/**
|
|
377
|
+
* What the step found, for a page to list rather than leave in the log:
|
|
378
|
+
* `{kind: 'egress_refused', subject: 'github.com'}` for a host the build
|
|
379
|
+
* pool's egress proxy refused.
|
|
380
|
+
*/
|
|
381
|
+
findings?: IEnvironmentBuildFinding[];
|
|
382
|
+
}
|
|
383
|
+
/** One finding of a build's step (E2-19): what it found, and what about. */
|
|
384
|
+
export interface IEnvironmentBuildFinding {
|
|
385
|
+
kind: string;
|
|
386
|
+
subject: string;
|
|
387
|
+
}
|
|
361
388
|
export interface IEnvironmentBuildRecord {
|
|
362
389
|
uid: string;
|
|
363
390
|
environmentUid: string;
|
|
@@ -367,6 +394,13 @@ export interface IEnvironmentBuildRecord {
|
|
|
367
394
|
region: string;
|
|
368
395
|
/** Counted from 1; a retry is the next attempt. */
|
|
369
396
|
attempt: number;
|
|
397
|
+
/**
|
|
398
|
+
* What this build is for: `build`, or `resolve` — a build that stops once
|
|
399
|
+
* the version has its lock (PLAN_ENVS.md E1-26). Absent from a Runtimes
|
|
400
|
+
* before that, and from every build recorded before the term existed, each
|
|
401
|
+
* of which is a build.
|
|
402
|
+
*/
|
|
403
|
+
kind?: string;
|
|
370
404
|
/** The request's key, suffixed with the variant and region. */
|
|
371
405
|
idempotencyKey: string;
|
|
372
406
|
/** `queued` when created; see `TERMINAL_ENVIRONMENT_BUILD_STATUSES`. */
|
|
@@ -379,6 +413,28 @@ export interface IEnvironmentBuildRecord {
|
|
|
379
413
|
* report with `passed: false` names the checks that failed and why.
|
|
380
414
|
*/
|
|
381
415
|
conformanceReport?: IEnvironmentConformanceReport | Record<string, never>;
|
|
416
|
+
/**
|
|
417
|
+
* Whether the retry route takes this build: cancelled, or failed under a
|
|
418
|
+
* code another attempt can pass (section 10). Said by Runtimes with the
|
|
419
|
+
* build, so a page offers Retry only where it would be taken (E2-19).
|
|
420
|
+
* Absent from a Runtimes before 1.0.36.
|
|
421
|
+
*/
|
|
422
|
+
retryable?: boolean;
|
|
423
|
+
/**
|
|
424
|
+
* The build's steps as its workflow ran them (E2-19), each kept by its
|
|
425
|
+
* name: `resolve`, `build`, `attest`, `smoke_test`… Absent from a Runtimes
|
|
426
|
+
* before 1.0.37 and from a build nothing reported for.
|
|
427
|
+
*/
|
|
428
|
+
steps?: IEnvironmentBuildStep[];
|
|
429
|
+
/**
|
|
430
|
+
* What the build spent (E2-19): its minutes by the daily quota's own rule —
|
|
431
|
+
* from its claim to its end, or to now while it runs — and those minutes at
|
|
432
|
+
* its variant's rate, in credits. `metered` is false where the provider
|
|
433
|
+
* bills the owner's own account (D-8). Absent from a Runtimes before them.
|
|
434
|
+
*/
|
|
435
|
+
buildMinutes?: number;
|
|
436
|
+
credits?: number;
|
|
437
|
+
metered?: boolean;
|
|
382
438
|
cacheHit: boolean;
|
|
383
439
|
correlationId: string;
|
|
384
440
|
requestedBy: string;
|
|
@@ -481,6 +537,13 @@ export interface IEnvironmentPublicationRecord {
|
|
|
481
537
|
publishedAt: string;
|
|
482
538
|
updatedAt: string;
|
|
483
539
|
snapshot: IEnvironmentPublicationSnapshot;
|
|
540
|
+
/**
|
|
541
|
+
* What a second of the snapshot's size class costs, priced by Runtimes when
|
|
542
|
+
* the publication is read (E2-15, E2-19): what a launch of it reserves by,
|
|
543
|
+
* since a stranger has no listing entry of it to read a rate from. Absent
|
|
544
|
+
* from a Runtimes before 1.0.35, and `null` for a class nothing prices.
|
|
545
|
+
*/
|
|
546
|
+
burningRate?: number | null;
|
|
484
547
|
/** What a conditional write names in `If-Match`. */
|
|
485
548
|
etag: string;
|
|
486
549
|
}
|
|
@@ -640,3 +703,57 @@ export interface IEnvironmentBuildLogPage {
|
|
|
640
703
|
complete: boolean;
|
|
641
704
|
}
|
|
642
705
|
export default IEnvironment;
|
|
706
|
+
/** Section 13's preview limits, per owner. */
|
|
707
|
+
export interface IEnvironmentQuotaLimits {
|
|
708
|
+
concurrentBuilds: number;
|
|
709
|
+
buildMinutesPerDay: number;
|
|
710
|
+
retainedVersions: number;
|
|
711
|
+
storedGib: number;
|
|
712
|
+
}
|
|
713
|
+
/** What an owner stores, and how it was measured. */
|
|
714
|
+
export interface IEnvironmentStoredHoldings {
|
|
715
|
+
gib: number;
|
|
716
|
+
bytes: number;
|
|
717
|
+
source: string;
|
|
718
|
+
meteredArtifacts: number;
|
|
719
|
+
unmeteredArtifacts: number;
|
|
720
|
+
}
|
|
721
|
+
/** What an owner holds against each limit right now. */
|
|
722
|
+
export interface IEnvironmentQuotaHoldings {
|
|
723
|
+
openBuilds: number;
|
|
724
|
+
buildMinutesToday: number;
|
|
725
|
+
retainedVersions: number;
|
|
726
|
+
storage: IEnvironmentStoredHoldings;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* An owner's build quotas and holdings, `GET /environment-quotas`: the numbers
|
|
730
|
+
* a `DL_ENV_QUOTA_EXCEEDED` refusal quotes, read before one (E2-19).
|
|
731
|
+
*/
|
|
732
|
+
export interface IEnvironmentQuotas {
|
|
733
|
+
ownerType: 'user' | 'organization';
|
|
734
|
+
ownerUid: string;
|
|
735
|
+
limits: IEnvironmentQuotaLimits;
|
|
736
|
+
holdings: IEnvironmentQuotaHoldings;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* One sandbox running a version. The caller's own carries its runtime uid,
|
|
740
|
+
* its digest and why it waits, if it does — the scheduler's own words, such
|
|
741
|
+
* as `Unschedulable: 0/6 nodes are available: 4 Insufficient cpu.`; anybody
|
|
742
|
+
* else's only its phase and start, so a page counts it without naming it.
|
|
743
|
+
*/
|
|
744
|
+
export interface IEnvironmentVersionSandbox {
|
|
745
|
+
/** `Pending` or `Running`: Kubernetes' phase of the sandbox's pod. */
|
|
746
|
+
phase: string;
|
|
747
|
+
startedAt: string;
|
|
748
|
+
yours: boolean;
|
|
749
|
+
runtimeUid?: string;
|
|
750
|
+
digest?: string;
|
|
751
|
+
waiting?: string;
|
|
752
|
+
/** Credits a second, for the caller's own: what it burns while it runs. */
|
|
753
|
+
burningRate?: number;
|
|
754
|
+
}
|
|
755
|
+
/** `GET /environment-versions/{uid}/sandboxes`. */
|
|
756
|
+
export interface IEnvironmentVersionSandboxes {
|
|
757
|
+
versionUid: string;
|
|
758
|
+
sandboxes: IEnvironmentVersionSandbox[];
|
|
759
|
+
}
|
package/lib/models/ItemType.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type IItemType = 'assignment' | 'authoring' | 'cell' | 'content' | 'credits' | 'dataset' | 'datasource' | 'document' | 'documentation' | 'environment' | 'exercise' | 'growth' | 'home' | 'invite' | 'lesson' | 'library' | 'mail' | 'management' | 'notebook' | 'onboarding' | 'organization' | 'page' | 'runtime' | 'runtime-snapshot' | 'settings' | 'share' | 'space' | 'storage' | 'success' | 'support' | 'tag' | 'team' | 'usage' | 'user' | 'undefined';
|
|
1
|
+
export type IItemType = 'assignment' | 'authoring' | 'cell' | 'content' | 'credits' | 'dataset' | 'datasource' | 'deck' | 'document' | 'documentation' | 'environment' | 'exercise' | 'growth' | 'home' | 'invite' | 'lesson' | 'library' | 'mail' | 'management' | 'notebook' | 'onboarding' | 'organization' | 'page' | 'runtime' | 'runtime-snapshot' | 'settings' | 'share' | 'space' | 'storage' | 'success' | 'support' | 'tag' | 'team' | 'usage' | 'user' | 'undefined';
|
|
2
2
|
export default IItemType;
|
package/lib/models/Runtime.d.ts
CHANGED
|
@@ -97,6 +97,12 @@ export interface IRuntimeRecord {
|
|
|
97
97
|
* Runtime credits reservation expiration timestamp
|
|
98
98
|
*/
|
|
99
99
|
expired_at?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Why the runtime's pod does not run yet, in Kubernetes' own words — the
|
|
102
|
+
* scheduler's `Unschedulable: 0/6 nodes are available: 4 Insufficient
|
|
103
|
+
* cpu.`, or an image that cannot be pulled — or empty once it runs.
|
|
104
|
+
*/
|
|
105
|
+
waiting?: string;
|
|
100
106
|
}
|
|
101
107
|
/**
|
|
102
108
|
* Runtime description (UI layer).
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { INotebook } from './Notebook';
|
|
2
2
|
import { IDocument } from './Document';
|
|
3
|
+
import { IDeck } from './Deck';
|
|
3
4
|
import { ICell } from './Cell';
|
|
4
5
|
import { IEnvironment } from './Environment';
|
|
5
6
|
import { ILesson } from './Lesson';
|
|
6
7
|
import { IExercise } from './Exercise';
|
|
7
8
|
import { IAssignment } from './Assignment';
|
|
8
|
-
export type ISpaceItem = INotebook | ICell | IEnvironment | ILesson | IExercise | IAssignment | IDocument;
|
|
9
|
+
export type ISpaceItem = INotebook | ICell | IEnvironment | ILesson | IExercise | IAssignment | IDocument | IDeck;
|
|
9
10
|
export default ISpaceItem;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** The `$id` of the JSON Schema these types are generated from. */
|
|
2
2
|
export declare const ENVIRONMENT_SCHEMA_ID = "https://datalayer.io/schemas/environments/v1alpha1/environment.json";
|
|
3
3
|
/** The sha256 of the schema text these types are generated from. */
|
|
4
|
-
export declare const ENVIRONMENT_SCHEMA_SHA256 = "
|
|
4
|
+
export declare const ENVIRONMENT_SCHEMA_SHA256 = "df0f8dc57cd82b8b0a77727071cb9a084a64c099703a8b9747ebe0f0958fe8f0";
|
|
5
5
|
/** The `apiVersion` an Environment document carries. */
|
|
6
6
|
export declare const ENVIRONMENT_API_VERSION = "environments.datalayer.io/v1alpha1";
|
|
7
7
|
/** The `kind` an Environment document carries. */
|
|
@@ -25,6 +25,8 @@ export interface BuildSecret {
|
|
|
25
25
|
name: string;
|
|
26
26
|
}
|
|
27
27
|
export interface BuildSpec {
|
|
28
|
+
dependencyFile?: DependencyFileSpec | null;
|
|
29
|
+
image?: ImageSourceSpec | null;
|
|
28
30
|
/** Default: `"packages"`. */
|
|
29
31
|
source?: 'packages' | 'dependencyFile' | 'dockerfile' | 'image';
|
|
30
32
|
}
|
|
@@ -35,12 +37,31 @@ export interface Compatibility {
|
|
|
35
37
|
regions?: string[];
|
|
36
38
|
variants?: VariantSet;
|
|
37
39
|
}
|
|
40
|
+
/** One immutable file the Environment bakes from an external source. */
|
|
41
|
+
export interface ContentsBuildEntry {
|
|
42
|
+
path: string;
|
|
43
|
+
/** Pattern: `^[0-9a-f]{64}$`. */
|
|
44
|
+
sha256: string;
|
|
45
|
+
/** Minimum: 0. */
|
|
46
|
+
sizeBytes?: number | null;
|
|
47
|
+
source: string;
|
|
48
|
+
}
|
|
49
|
+
/** A `requirements.txt`, a `pyproject.toml` with its `uv.lock`, or a conda `environment.yml` (E3-01, E3-02). */
|
|
50
|
+
export interface DependencyFileSpec {
|
|
51
|
+
/** Default: `""`. */
|
|
52
|
+
content?: string;
|
|
53
|
+
/** Default: `""`. */
|
|
54
|
+
lockContent?: string;
|
|
55
|
+
/** Default: `"requirements"`. */
|
|
56
|
+
sourceFormat?: 'requirements' | 'pyproject' | 'conda';
|
|
57
|
+
}
|
|
38
58
|
export interface EnvironmentSpec {
|
|
39
59
|
base: Base;
|
|
40
60
|
build?: BuildSpec;
|
|
41
61
|
buildSecrets?: BuildSecret[];
|
|
42
62
|
commands?: Commands;
|
|
43
63
|
compatibility?: Compatibility;
|
|
64
|
+
contentsBuild?: ContentsBuildEntry[];
|
|
44
65
|
/** Default: `"sandbox-contract/v1"`. */
|
|
45
66
|
contract?: string;
|
|
46
67
|
env?: Record<string, string>;
|
|
@@ -58,6 +79,13 @@ export interface FileEntry {
|
|
|
58
79
|
/** Minimum: 0. */
|
|
59
80
|
sizeBytes?: number | null;
|
|
60
81
|
}
|
|
82
|
+
/** An existing OCI image, imported as the build's base (E3-04). */
|
|
83
|
+
export interface ImageSourceSpec {
|
|
84
|
+
/** Pattern: `^dlsec_[0-9A-Za-z]+$`. */
|
|
85
|
+
credentialSecretId?: string | null;
|
|
86
|
+
/** Default: `""`. */
|
|
87
|
+
reference?: string;
|
|
88
|
+
}
|
|
61
89
|
export interface Language {
|
|
62
90
|
name?: 'python';
|
|
63
91
|
/** Pattern: `^3\.\d+$`. */
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
/** The `$id` of the JSON Schema these types are generated from. */
|
|
7
7
|
export const ENVIRONMENT_SCHEMA_ID = 'https://datalayer.io/schemas/environments/v1alpha1/environment.json';
|
|
8
8
|
/** The sha256 of the schema text these types are generated from. */
|
|
9
|
-
export const ENVIRONMENT_SCHEMA_SHA256 = '
|
|
9
|
+
export const ENVIRONMENT_SCHEMA_SHA256 = 'df0f8dc57cd82b8b0a77727071cb9a084a64c099703a8b9747ebe0f0958fe8f0';
|
|
10
10
|
/** The `apiVersion` an Environment document carries. */
|
|
11
11
|
export const ENVIRONMENT_API_VERSION = 'environments.datalayer.io/v1alpha1';
|
|
12
12
|
/** The `kind` an Environment document carries. */
|
package/lib/models/index.d.ts
CHANGED