@datalayer/agent-runtimes 1.3.85 → 1.3.87
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/components/teams/A2ATeamGraph.d.ts +115 -20
- package/lib/components/teams/A2ATeamGraph.js +246 -109
- package/lib/components/teams/index.d.ts +1 -0
- package/lib/components/teams/index.js +1 -0
- package/lib/components/teams/sceneStage.d.ts +120 -0
- package/lib/components/teams/sceneStage.js +170 -0
- package/lib/components/teams/useA2ATeam.d.ts +92 -20
- package/lib/components/teams/useA2ATeam.js +313 -101
- package/lib/examples/ScenesExample.d.ts +26 -0
- package/lib/examples/ScenesExample.js +241 -0
- package/lib/examples/example-selector.js +1 -0
- package/lib/examples/exampleGroups.js +3 -0
- package/lib/examples/index.d.ts +1 -0
- package/lib/examples/index.js +1 -0
- package/lib/examples/main.js +4 -0
- package/lib/specs/index.d.ts +1 -0
- package/lib/specs/index.js +1 -0
- package/lib/specs/mcpServers.js +8 -2
- package/lib/specs/sceneSchema.d.ts +8 -0
- package/lib/specs/sceneSchema.js +852 -0
- package/lib/specs/scenes.d.ts +21 -0
- package/lib/specs/scenes.js +1191 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +1 -0
- package/lib/types/scenes.d.ts +207 -0
- package/lib/types/scenes.js +5 -0
- package/package.json +3 -3
- package/scripts/codegen/generate_agents.py +1 -0
- package/scripts/codegen/generate_envvars.py +1 -1
- package/scripts/codegen/generate_scenes.py +343 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { Button, Flash, Heading, Text, Textarea, UnderlineNav, } from '@primer/react';
|
|
4
|
+
import { Box } from '@datalayer/primer-addons';
|
|
5
|
+
import { AnonymousKeyExpired } from '@datalayer/core/lib/components/anonymous/AnonymousKeyExpired';
|
|
6
|
+
import { AnonymousKeyTimer } from '@datalayer/core/lib/components/anonymous/AnonymousKeyTimer';
|
|
7
|
+
import { Streamdown } from 'streamdown';
|
|
8
|
+
import { ThemedProvider } from './utils/themedProvider';
|
|
9
|
+
import { useBrowserInference } from '../hooks/useBrowserInference';
|
|
10
|
+
import { useAnonymousSessionStore } from '../runtimes/browser/anonymousToken';
|
|
11
|
+
import { connectA2APeer } from '../runtimes/browser/a2aPeer';
|
|
12
|
+
import { A2ATeamGraph, NOTEBOOK_AND_WORDS, PERSON, SceneView, sceneCuesOf, sceneMemberUrl, sceneRuntimePorts, sceneStageOf, teamConnectionsOf, teamToolClassifier, useA2ATeam, } from '../components/teams';
|
|
13
|
+
import { listSceneSpecs } from '../specs/scenes';
|
|
14
|
+
import { classifyToolCall, traceA2AFetch, useAgentInspector, } from '../components/inspector';
|
|
15
|
+
/** Where the members on a runtime are, by application id: the local ports, unless a variable says. */
|
|
16
|
+
const PORTS = sceneRuntimePorts();
|
|
17
|
+
/**
|
|
18
|
+
* Reach a member on a runtime: read its card at `url`, its traffic recorded
|
|
19
|
+
* as spans for the inspectors and the transcript, as asked by `asker`.
|
|
20
|
+
*/
|
|
21
|
+
function useReached(url, asker, name, connections, tracer) {
|
|
22
|
+
const [reached, setReached] = useState({ peer: null, error: null });
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
let current = true;
|
|
25
|
+
setReached({ peer: null, error: null });
|
|
26
|
+
connectA2APeer({
|
|
27
|
+
url,
|
|
28
|
+
fetch: traceA2AFetch(globalThis.fetch.bind(globalThis), {
|
|
29
|
+
tracer,
|
|
30
|
+
asker,
|
|
31
|
+
peer: name,
|
|
32
|
+
classifyTool: teamToolClassifier(connections, classifyToolCall),
|
|
33
|
+
}),
|
|
34
|
+
})
|
|
35
|
+
.then(peer => current && setReached({ peer, error: null }))
|
|
36
|
+
.catch(error => current &&
|
|
37
|
+
setReached({
|
|
38
|
+
peer: null,
|
|
39
|
+
error: error instanceof Error ? error.message : String(error),
|
|
40
|
+
}));
|
|
41
|
+
return () => {
|
|
42
|
+
current = false;
|
|
43
|
+
};
|
|
44
|
+
}, [url, asker, name, connections, tracer]);
|
|
45
|
+
return reached;
|
|
46
|
+
}
|
|
47
|
+
/** The members of a scene that run on a runtime, each with its address and connections. */
|
|
48
|
+
function runtimeMembersOf(stage) {
|
|
49
|
+
const env = import.meta.env;
|
|
50
|
+
return stage.members
|
|
51
|
+
.filter(member => member.runsIn === 'runtime')
|
|
52
|
+
.map(member => ({
|
|
53
|
+
...member,
|
|
54
|
+
url: sceneMemberUrl(member.app.id, env, PORTS),
|
|
55
|
+
connections: teamConnectionsOf(member.app),
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
/** One member on a runtime: reached, and told to the scene. */
|
|
59
|
+
function ReachMember({ member, asker, tracer, onReached, }) {
|
|
60
|
+
const reached = useReached(member.url, asker, member.app.name, member.connections, tracer);
|
|
61
|
+
useEffect(() => onReached(member.id, reached), [member.id, reached, onReached]);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/** What a member not reached needs: its application's setup, and how to serve it. */
|
|
65
|
+
function memberNeeds(member, error) {
|
|
66
|
+
return [
|
|
67
|
+
`${member.app.name} is not reachable at ${member.url}: ${error}`,
|
|
68
|
+
...member.setup,
|
|
69
|
+
`Serve it with python examples/sales-accounting-a2a/serve_scenes.py (npm run examples does), or set VITE_A2A_${member.app.id
|
|
70
|
+
.replace(/-/g, '_')
|
|
71
|
+
.toUpperCase()}_URL to where it runs.`,
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
function Scene({ scene }) {
|
|
75
|
+
const stage = useMemo(() => sceneStageOf(scene), [scene]);
|
|
76
|
+
const entry = stage.entry;
|
|
77
|
+
const entryInBrowser = entry.runsIn === 'browser';
|
|
78
|
+
const runtimeMembers = useMemo(() => runtimeMembersOf(stage), [stage]);
|
|
79
|
+
const { inference, needsSignIn, anonymous } = useBrowserInference(entryInBrowser);
|
|
80
|
+
// One tracer of what every member does: each inspector shows its own.
|
|
81
|
+
const { tracer: inspector } = useAgentInspector();
|
|
82
|
+
const [reached, setReached] = useState({});
|
|
83
|
+
const onReached = useMemo(() => (id, found) => setReached(prev => prev[id]?.peer === found.peer && prev[id]?.error === found.error
|
|
84
|
+
? prev
|
|
85
|
+
: { ...prev, [id]: found }), []);
|
|
86
|
+
const reachedOf = (id) => reached[id] ?? { peer: null, error: null };
|
|
87
|
+
// The entry's peers over A2A, in the cast's order; the entry itself when
|
|
88
|
+
// it runs on a runtime.
|
|
89
|
+
const peerOptions = useMemo(() => stage.peers.map(peer => {
|
|
90
|
+
const member = runtimeMembers.find(one => one.id === peer.id);
|
|
91
|
+
return {
|
|
92
|
+
app: peer.app,
|
|
93
|
+
peer: reached[peer.id]?.peer ?? null,
|
|
94
|
+
connections: member?.connections ?? [],
|
|
95
|
+
...(stage.opensFirst === peer.id
|
|
96
|
+
? { greeting: peer.cast.persona.line }
|
|
97
|
+
: {}),
|
|
98
|
+
};
|
|
99
|
+
}), [stage, runtimeMembers, reached]);
|
|
100
|
+
const team = useA2ATeam({
|
|
101
|
+
entry: entry.app,
|
|
102
|
+
peers: peerOptions,
|
|
103
|
+
entryPeer: entryInBrowser ? undefined : reachedOf(entry.id).peer,
|
|
104
|
+
inference,
|
|
105
|
+
accept: NOTEBOOK_AND_WORDS,
|
|
106
|
+
inspector,
|
|
107
|
+
});
|
|
108
|
+
// The script's cues, labelled by the entry's starters (A-13): chips in
|
|
109
|
+
// its balloon while it waits for a question.
|
|
110
|
+
const suggestions = useMemo(() => sceneCuesOf(scene, entry.app.interface.starters ?? []), [scene, entry.app]);
|
|
111
|
+
const [draft, setDraft] = useState('');
|
|
112
|
+
const composer = useRef(null);
|
|
113
|
+
// Under the graph: where a notebook a member gives runs.
|
|
114
|
+
const notebookArea = useRef(null);
|
|
115
|
+
const send = (text) => {
|
|
116
|
+
setDraft('');
|
|
117
|
+
void team.send(text);
|
|
118
|
+
};
|
|
119
|
+
// The members as the transcript names them: the spans' services, and the
|
|
120
|
+
// connections a tool call is of.
|
|
121
|
+
const transcriptMembers = useMemo(() => stage.members.map(member => ({
|
|
122
|
+
id: member.app.id,
|
|
123
|
+
name: member.app.name,
|
|
124
|
+
connections: runtimeMembers.find(one => one.id === member.id)?.connections ?? [],
|
|
125
|
+
})), [stage, runtimeMembers]);
|
|
126
|
+
const whereOf = (member) => member.runsIn === 'browser'
|
|
127
|
+
? 'in your browser'
|
|
128
|
+
: `on a runtime, ${new URL(runtimeMembers.find(one => one.id === member.id)?.url ?? 'http://runtime').host}`;
|
|
129
|
+
const aboutOf = (member) => {
|
|
130
|
+
const peer = reachedOf(member.id).peer;
|
|
131
|
+
const url = runtimeMembers.find(one => one.id === member.id)?.url;
|
|
132
|
+
return {
|
|
133
|
+
name: member.app.name,
|
|
134
|
+
spec: `${member.app.id}:${member.app.version}`,
|
|
135
|
+
model: member.app.model || undefined,
|
|
136
|
+
where: whereOf(member),
|
|
137
|
+
description: peer?.card.description || member.app.description || undefined,
|
|
138
|
+
skills: peer?.card.skills.map(skill => skill.name),
|
|
139
|
+
protocol: peer ? 'a2a' : undefined,
|
|
140
|
+
url: peer ? url : undefined,
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
const notReached = runtimeMembers.filter(member => reachedOf(member.id).error);
|
|
144
|
+
const notebookGiver = stage.peers[0] ?? entry;
|
|
145
|
+
return (_jsxs(Box, { "data-scene-example": scene.id, children: [_jsx(Text, { as: "p", sx: { color: 'fg.muted', mt: 0 }, "data-scene-assumes": "", children: stage.assumes }), anonymous.status === 'active' && anonymous.expiresAt && (_jsx(Box, { sx: { mb: 3 }, children: _jsx(AnonymousKeyTimer, { expiresAt: anonymous.expiresAt, grantedMs: anonymous.grantedMs, label: `${entry.app.name}'s trial key`, onExpire: () => useAnonymousSessionStore.getState().expire() }) })), anonymous.status === 'expired' && (_jsx(Box, { sx: { mb: 3 }, children: _jsx(AnonymousKeyExpired, { agentName: entry.app.name, onSignedIn: () => useAnonymousSessionStore.getState().clear() }) })), entryInBrowser && needsSignIn && (_jsxs(Flash, { variant: "warning", sx: { mb: 3 }, children: [entry.app.name, " asks its model through the Datalayer inference service: sign in, or wait for a visitor\u2019s trial key."] })), notReached.map(member => (_jsx(Flash, { variant: "danger", sx: { mb: 3 }, "data-scene-needs": member.app.id, children: memberNeeds(member, reachedOf(member.id).error ?? '').map(line => (_jsx(Text, { as: "p", sx: { m: 0 }, children: line }, line))) }, member.id))), runtimeMembers.map(member => (_jsx(ReachMember, { member: member,
|
|
146
|
+
// Its requests are the entry's, or the person's own when the
|
|
147
|
+
// page asks it itself.
|
|
148
|
+
asker: member.entry ? PERSON : entry.app.name, tracer: inspector, onReached: onReached }, member.id))), _jsx(Box, { sx: {
|
|
149
|
+
border: '1px solid',
|
|
150
|
+
borderColor: 'border.default',
|
|
151
|
+
borderRadius: 2,
|
|
152
|
+
bg: 'canvas.subtle',
|
|
153
|
+
px: 2,
|
|
154
|
+
pt: 2,
|
|
155
|
+
mb: 3,
|
|
156
|
+
}, children: _jsx(SceneView, { members: transcriptMembers, tracer: inspector, emptyText: `Nothing said yet: ask ${entry.app.name} with one of the suggestions.`, children: _jsx(A2ATeamGraph, { entry: {
|
|
157
|
+
id: entry.app.id,
|
|
158
|
+
name: entry.app.name,
|
|
159
|
+
emoji: entry.cast.persona.face || entry.app.emoji,
|
|
160
|
+
character: entry.app.interface.assistant ?? 'paperclip',
|
|
161
|
+
where: whereOf(entry),
|
|
162
|
+
persona: team.entryPersona,
|
|
163
|
+
onToggle: () => composer.current?.focus(),
|
|
164
|
+
conversationLabel: `Ask ${entry.app.name}`,
|
|
165
|
+
onAway: team.setEntryAway,
|
|
166
|
+
history: team.entryHistory,
|
|
167
|
+
connections: runtimeMembers.find(one => one.id === entry.id)
|
|
168
|
+
?.connections,
|
|
169
|
+
expandTarget: notebookArea,
|
|
170
|
+
notebookTitle: `${notebookGiver.app.name}’s notebook`,
|
|
171
|
+
suggestions: team.ready && !team.busy ? suggestions : undefined,
|
|
172
|
+
onSuggestion: suggestion => send(suggestion.prompt),
|
|
173
|
+
inspector,
|
|
174
|
+
onStop: team.busy ? team.stop : undefined,
|
|
175
|
+
about: aboutOf(entry),
|
|
176
|
+
}, peers: stage.peers.map(peer => {
|
|
177
|
+
const kept = team.peers.find(one => one.id === peer.app.id);
|
|
178
|
+
return {
|
|
179
|
+
id: peer.app.id,
|
|
180
|
+
name: peer.app.name,
|
|
181
|
+
emoji: reachedOf(peer.id).peer?.face?.emoji ||
|
|
182
|
+
peer.cast.persona.face ||
|
|
183
|
+
peer.app.emoji,
|
|
184
|
+
character: peer.app.interface.assistant ?? 'wizard',
|
|
185
|
+
where: whereOf(peer),
|
|
186
|
+
persona: kept?.persona ?? team.peerPersona,
|
|
187
|
+
onAway: kept?.setAway,
|
|
188
|
+
history: kept?.history,
|
|
189
|
+
connections: runtimeMembers.find(one => one.id === peer.id)
|
|
190
|
+
?.connections,
|
|
191
|
+
inspector,
|
|
192
|
+
about: aboutOf(peer),
|
|
193
|
+
};
|
|
194
|
+
}), flows: team.flows, calls: team.calls, links: stage.links.map(link => ({
|
|
195
|
+
from: stage.members.find(m => m.id === link.from)?.app.id ??
|
|
196
|
+
link.from,
|
|
197
|
+
to: stage.members.find(m => m.id === link.to)?.app.id ?? link.to,
|
|
198
|
+
})), positions: Object.fromEntries(stage.members
|
|
199
|
+
.filter(member => stage.positions[member.id])
|
|
200
|
+
.map(member => [member.app.id, stage.positions[member.id]])), connected: Object.fromEntries(stage.peers.map(peer => [
|
|
201
|
+
peer.app.id,
|
|
202
|
+
reachedOf(peer.id).peer !== null,
|
|
203
|
+
])), labels: Object.fromEntries(stage.peers.map(peer => {
|
|
204
|
+
const found = reachedOf(peer.id).peer;
|
|
205
|
+
return [
|
|
206
|
+
peer.app.id,
|
|
207
|
+
found ? `A2A · ${found.skill.name}` : 'A2A · not connected',
|
|
208
|
+
];
|
|
209
|
+
})),
|
|
210
|
+
// Room for the balloons: suggestions, *more* and a notebook.
|
|
211
|
+
balloonRoom: 320 }) }) }), _jsx(Box, { ref: notebookArea, sx: { mb: team.notebook ? 3 : 0 }, "data-team-notebook-placement": "under-graph" }), _jsxs(Box, { sx: { display: 'flex', gap: 3, flexWrap: 'wrap' }, children: [_jsxs(Box, { sx: { flex: '1 1 420px', minWidth: 0 }, children: [_jsxs(Heading, { as: "h3", sx: { fontSize: 2, mb: 2 }, children: ["Ask ", entry.app.name] }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, mt: 0 }, children: "Or choose one of its suggestions in its balloon: the script\u2019s cues." }), _jsx(Textarea, { ref: composer, block: true, rows: 3, value: draft, placeholder: suggestions[0]?.prompt ?? 'Ask…', onChange: event => setDraft(event.target.value), onKeyDown: event => {
|
|
212
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
213
|
+
event.preventDefault();
|
|
214
|
+
send(draft);
|
|
215
|
+
}
|
|
216
|
+
} }), _jsxs(Box, { sx: { display: 'flex', gap: 2, mt: 2 }, children: [_jsx(Button, { variant: "primary", disabled: !team.ready || team.busy || !draft.trim(), onClick: () => send(draft), children: "Ask" }), team.busy && _jsx(Button, { onClick: team.stop, children: "Stop" })] }), _jsx(Box, { sx: { mt: 3 }, "data-team-conversation": "", children: team.turns.map((turn, index) => (_jsxs(Box, { sx: {
|
|
217
|
+
p: 2,
|
|
218
|
+
mb: 2,
|
|
219
|
+
borderRadius: 2,
|
|
220
|
+
bg: turn.role === 'user' ? 'accent.subtle' : 'canvas.subtle',
|
|
221
|
+
}, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', display: 'block' }, children: turn.role === 'user' ? PERSON : entry.app.name }), _jsx(Streamdown, { children: turn.text })] }, index))) })] }), _jsxs(Box, { sx: { flex: '1 1 360px', minWidth: 0 }, children: [!team.notebook && stage.peers.length > 0 && (_jsxs(_Fragment, { children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2, mb: 2 }, children: "The report" }), _jsx(Box, { sx: {
|
|
222
|
+
p: 3,
|
|
223
|
+
border: '1px solid',
|
|
224
|
+
borderColor: 'border.default',
|
|
225
|
+
borderRadius: 2,
|
|
226
|
+
minHeight: 120,
|
|
227
|
+
}, "data-team-report": "", children: team.report ? (_jsx(Streamdown, { children: team.report })) : (_jsx(Text, { sx: { color: 'fg.muted' }, children: "What the last member asked returns appears here, as it returned it, or as a notebook to run when it gives one." })) })] })), scene.setup.length > 0 && (_jsxs(Box, { sx: { mt: 3 }, "data-scene-setup": "", children: [_jsx(Heading, { as: "h3", sx: { fontSize: 1, mb: 1 }, children: "What this scene needs" }), scene.setup.map(line => (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', m: 0 }, children: line }, line)))] }))] })] })] }));
|
|
228
|
+
}
|
|
229
|
+
function Scenes() {
|
|
230
|
+
const scenes = useMemo(() => listSceneSpecs(), []);
|
|
231
|
+
const [selected, setSelected] = useState(scenes[0]?.id ?? '');
|
|
232
|
+
const scene = scenes.find(one => one.id === selected) ?? scenes[0];
|
|
233
|
+
return (_jsxs(Box, { sx: { p: 4, maxWidth: 1080, mx: 'auto' }, children: [_jsx(Heading, { as: "h2", sx: { fontSize: 4, mb: 1 }, children: "Scenes" }), _jsxs(Text, { as: "p", sx: { color: 'fg.muted', mt: 0 }, children: ["The catalogue\u2019s scenes, played against the local servers: each member on a runtime is served over A2A by ", _jsx("code", { children: "serve_scenes.py" }), "; the entry in your browser asks on your token or a visitor\u2019s trial key."] }), _jsx(UnderlineNav, { "aria-label": "Scenes", sx: { mb: 3 }, children: scenes.map(one => (_jsxs(UnderlineNav.Item, { "aria-current": one.id === scene?.id ? 'page' : undefined, onSelect: event => {
|
|
234
|
+
event.preventDefault();
|
|
235
|
+
setSelected(one.id);
|
|
236
|
+
}, "data-scene-tab": one.id, children: [one.emoji, " ", one.name] }, one.id))) }), scene && _jsx(Scene, { scene: scene }, scene.id)] }));
|
|
237
|
+
}
|
|
238
|
+
export function ScenesExample() {
|
|
239
|
+
return (_jsx(ThemedProvider, { children: _jsx(Scenes, {}) }));
|
|
240
|
+
}
|
|
241
|
+
export default ScenesExample;
|
|
@@ -112,6 +112,7 @@ export const EXAMPLE_ENTRIES = [
|
|
|
112
112
|
// for one sandbox — and a second one that would not agree with the first.
|
|
113
113
|
['example', 'loop', 'workspace', 'sandbox', 'owns-sandbox-control']),
|
|
114
114
|
makeEntry('LoopAppComputerExample', () => import('./LoopAppComputerExample'), 'An application beside its computer: what its agent ran on its sandbox, its files, and Take over and Hand back (LOOP R-23).', ['example', 'loop', 'app', 'computer', 'sandbox', 'owns-sandbox-control']),
|
|
115
|
+
makeEntry('ScenesExample', () => import('./ScenesExample'), 'The scenes of the catalogue in tabs — Sales & Accounting, Month-end close, Crop monitoring, Disaster assessment — each its graph and transcript, its cues as suggestions, played against the local servers (LOOP A-15).', ['example', 'loop', 'scenes', 'a2a', 'agentspecs', 'team']),
|
|
115
116
|
makeEntry('LoopShellExample', () => import('./LoopShellExample'), 'The Loop shell at its most naked: a blank canvas, a floating draggable prompt, and an editor selector in the corner — none, notebook or document.',
|
|
116
117
|
// `owns-sandbox-control`: the shell is pinned to the browser sandbox, so
|
|
117
118
|
// the page's selector would offer three targets it cannot move to.
|
|
@@ -23,7 +23,10 @@ export const EXAMPLE_GROUP_ORDER = [
|
|
|
23
23
|
'CopilotKit',
|
|
24
24
|
];
|
|
25
25
|
export const getExampleGroup = (id) => {
|
|
26
|
+
// The library of specs, the Loop shells, and the scenes of the catalogue
|
|
27
|
+
// (LOOP A-15): the applications and what is staged with them.
|
|
26
28
|
if (id === 'AgentspecsExample' ||
|
|
29
|
+
id === 'ScenesExample' ||
|
|
27
30
|
id.startsWith('Loop') ||
|
|
28
31
|
id === 'DecksAgent') {
|
|
29
32
|
return 'Apps';
|
package/lib/examples/index.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export { default as AgentCodemodeExample } from './AgentCodemodeExample';
|
|
|
27
27
|
export { default as AgentCodeSandboxesExample } from './AgentCodeSandboxesExample';
|
|
28
28
|
export { default as AgentDecideExample } from './AgentDecideExample';
|
|
29
29
|
export { default as AgentA2ATeamExample } from './AgentA2ATeamExample';
|
|
30
|
+
export { default as ScenesExample } from './ScenesExample';
|
|
30
31
|
export { default as AgentEvalsExample } from './AgentEvalsExample';
|
|
31
32
|
export { default as AgentGuardrailsExample } from './AgentGuardrailsExample';
|
|
32
33
|
export { default as AgentHooksExample } from './AgentHooksExample';
|
package/lib/examples/index.js
CHANGED
|
@@ -33,6 +33,7 @@ export { default as AgentCodemodeExample } from './AgentCodemodeExample';
|
|
|
33
33
|
export { default as AgentCodeSandboxesExample } from './AgentCodeSandboxesExample';
|
|
34
34
|
export { default as AgentDecideExample } from './AgentDecideExample';
|
|
35
35
|
export { default as AgentA2ATeamExample } from './AgentA2ATeamExample';
|
|
36
|
+
export { default as ScenesExample } from './ScenesExample';
|
|
36
37
|
export { default as AgentEvalsExample } from './AgentEvalsExample';
|
|
37
38
|
export { default as AgentGuardrailsExample } from './AgentGuardrailsExample';
|
|
38
39
|
export { default as AgentHooksExample } from './AgentHooksExample';
|
package/lib/examples/main.js
CHANGED
|
@@ -62,6 +62,9 @@ const ANONYMOUS_EXAMPLES = new Set([
|
|
|
62
62
|
// The Sales and Accounting team: Sales in the page on a visitor's trial
|
|
63
63
|
// key, Accounting on the local server, which answers the machine itself.
|
|
64
64
|
'AgentA2ATeamExample',
|
|
65
|
+
// The scenes of the catalogue: each entry in the page on a visitor's trial
|
|
66
|
+
// key, the members on a runtime on local servers that answer the machine.
|
|
67
|
+
'ScenesExample',
|
|
65
68
|
// Decide, on the local agent-runtimes server as above: Jev is asked
|
|
66
69
|
// through the server's ai-inference, with the server's own key.
|
|
67
70
|
'AgentDecideExample',
|
|
@@ -1045,6 +1048,7 @@ const ExampleAppThemed = ({ selectedExample, isChangingExample, error, ExampleCo
|
|
|
1045
1048
|
'LoopStrategyExample',
|
|
1046
1049
|
'LoopAppComputerExample',
|
|
1047
1050
|
'AgentspecsExample',
|
|
1051
|
+
'ScenesExample',
|
|
1048
1052
|
];
|
|
1049
1053
|
const loopOrder = (id) => {
|
|
1050
1054
|
const index = LOOP_ORDER.indexOf(id);
|
package/lib/specs/index.d.ts
CHANGED
package/lib/specs/index.js
CHANGED
package/lib/specs/mcpServers.js
CHANGED
|
@@ -68,12 +68,18 @@ export const EARTHDATA_MCP_SERVER_0_0_1 = {
|
|
|
68
68
|
emoji: '🌍',
|
|
69
69
|
url: '',
|
|
70
70
|
command: 'npx',
|
|
71
|
-
args: [
|
|
71
|
+
args: [
|
|
72
|
+
'-y',
|
|
73
|
+
'mcp-remote',
|
|
74
|
+
'https://mcp.datalayer.run/mcp?only=earthdata',
|
|
75
|
+
'--header',
|
|
76
|
+
'Authorization: Bearer ${DATALAYER_API_KEY}',
|
|
77
|
+
],
|
|
72
78
|
transport: 'stdio',
|
|
73
79
|
enabled: true,
|
|
74
80
|
isAvailable: false,
|
|
75
81
|
tools: [],
|
|
76
|
-
requiredEnvVars: ['
|
|
82
|
+
requiredEnvVars: ['DATALAYER_API_KEY:0.0.1'],
|
|
77
83
|
};
|
|
78
84
|
export const EURUS_MCP_SERVER_0_0_1 = {
|
|
79
85
|
id: 'eurus',
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The scene spec's JSON Schema (`loop.scene/v1`), generated from agentspecs by
|
|
3
|
+
* `scripts/codegen/generate_scenes.py`. Do not edit.
|
|
4
|
+
*
|
|
5
|
+
* @module specs/sceneSchema
|
|
6
|
+
*/
|
|
7
|
+
import type { JsonSchema } from './appspecSchema';
|
|
8
|
+
export declare const SCENE_SCHEMA: JsonSchema;
|