@datalayer/agent-runtimes 1.3.59 → 1.3.60

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.
Files changed (49) hide show
  1. package/lib/chat/ChatFloating.d.ts +11 -1
  2. package/lib/chat/ChatFloating.js +6 -2
  3. package/lib/chat/assistant/AssistantStage.d.ts +7 -1
  4. package/lib/chat/assistant/AssistantStage.js +5 -3
  5. package/lib/chat/assistant/DecisionAsk.d.ts +31 -0
  6. package/lib/chat/assistant/DecisionAsk.js +96 -0
  7. package/lib/chat/assistant/SpeechBalloon.d.ts +11 -2
  8. package/lib/chat/assistant/SpeechBalloon.js +5 -4
  9. package/lib/chat/assistant/decisions.d.ts +104 -0
  10. package/lib/chat/assistant/decisions.js +161 -0
  11. package/lib/chat/marks/toolMarks.js +2 -2
  12. package/lib/config/AgentConfiguration.d.ts +2 -1
  13. package/lib/config/AgentConfiguration.js +2 -2
  14. package/lib/examples/AgentDecideExample.d.ts +24 -0
  15. package/lib/examples/AgentDecideExample.js +73 -0
  16. package/lib/examples/AgentNotificationsExample.js +1 -1
  17. package/lib/examples/AgentSkillsExample.js +1 -1
  18. package/lib/examples/AgentspecsExample.js +3 -3
  19. package/lib/examples/example-selector.js +1 -0
  20. package/lib/examples/index.d.ts +1 -0
  21. package/lib/examples/index.js +1 -0
  22. package/lib/examples/main.js +3 -0
  23. package/lib/loop/apps/appspec.js +4 -4
  24. package/lib/loop/apps/checks.js +6 -6
  25. package/lib/loop/apps/rules.js +2 -2
  26. package/lib/loop/plugins/assistant/index.d.ts +14 -2
  27. package/lib/loop/plugins/assistant/index.js +13 -4
  28. package/lib/specs/actions.d.ts +1 -1
  29. package/lib/specs/actions.js +1 -1
  30. package/lib/specs/agents/agents.js +197 -192
  31. package/lib/specs/apps.js +13 -13
  32. package/lib/specs/appspecSchema.js +3 -3
  33. package/lib/specs/backendTools.d.ts +31 -0
  34. package/lib/specs/{tools.js → backendTools.js} +48 -48
  35. package/lib/specs/cogs.js +8 -7
  36. package/lib/specs/frames.js +5 -5
  37. package/lib/specs/index.d.ts +1 -1
  38. package/lib/specs/index.js +1 -1
  39. package/lib/stores/agentRuntimeStore.js +2 -2
  40. package/lib/types/agentspecs.d.ts +7 -5
  41. package/lib/types/config.d.ts +2 -2
  42. package/lib/types/tools.d.ts +3 -3
  43. package/package.json +1 -1
  44. package/scripts/codegen/generate_agents.py +23 -12
  45. package/scripts/codegen/generate_apps.py +3 -2
  46. package/scripts/codegen/{generate_tools.py → generate_backend_tools.py} +29 -29
  47. package/scripts/codegen/generate_cogs.py +2 -2
  48. package/scripts/codegen/generate_frames.py +2 -2
  49. package/lib/specs/tools.d.ts +0 -31
@@ -0,0 +1,73 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * Decide: typed decisions asked of Jev (`cloudflare:wrk/typesafe/jev`), the
8
+ * typed-decision model, from the chat and from the floating assistant.
9
+ *
10
+ * The *Decide* application of the catalogue (agentspecs `apps/decide.yaml`)
11
+ * in the LOOP workspace, on the Local target: its agent — `example-simple`
12
+ * with the `decide` tool — runs on the local agent-runtimes server, and
13
+ * answers a question about a text by asking a typed decision. The floating
14
+ * assistant beside it offers *Ask a decision* in its balloon: the situation,
15
+ * the question and its type, asked through the same server's
16
+ * `/api/v1/configure/inference/decisions`, the route that asks as `decide`
17
+ * does, with the same token.
18
+ *
19
+ * The server needs ai-inference: start it with
20
+ * `AGENT_RUNTIMES_INFERENCE_PROVIDER_OVERRIDE=datalayer`,
21
+ * `DATALAYER_AI_INFERENCE_URL=https://r1.datalayer.run` and
22
+ * `DATALAYER_AI_INFERENCE_API_KEY` set from `DATALAYER_API_KEY`. Another
23
+ * server than `http://localhost:8765` is named with `?agentRuntimesUrl=`.
24
+ *
25
+ * @module examples/AgentDecideExample
26
+ */
27
+ import { useMemo } from 'react';
28
+ import { configurePlugin } from '@datalayer/reactor';
29
+ import { Heading, Text } from '@primer/react';
30
+ import { Box, setupPrimerPortals } from '@datalayer/primer-addons';
31
+ import { ThemedProvider } from './utils/themedProvider';
32
+ import { resolveExampleAgentRuntimesUrl } from './utils/useExampleAgentRuntimesUrl';
33
+ import { AppRenderer, appDatalayerCreatePayload, } from '../loop/apps/AppRenderer';
34
+ import { AssistantCharactersPlugin } from '../loop/plugins/assistant-characters';
35
+ import { LoopAssistantPlugin } from '../loop/plugins/assistant';
36
+ import { APP_CATALOGUE } from '../specs/apps';
37
+ setupPrimerPortals();
38
+ /** The local server: `?agentRuntimesUrl=` when given, else the examples' own. */
39
+ function serverUrlOf() {
40
+ const named = typeof window === 'undefined'
41
+ ? null
42
+ : new URLSearchParams(window.location.search).get('agentRuntimesUrl');
43
+ return resolveExampleAgentRuntimesUrl('local', named ?? undefined);
44
+ }
45
+ const AgentDecideExample = () => {
46
+ const app = APP_CATALOGUE['decide'];
47
+ const serverUrl = useMemo(serverUrlOf, []);
48
+ // Made once: a new plugin on a render restarts the workspace.
49
+ const plugins = useMemo(() => [
50
+ AssistantCharactersPlugin,
51
+ configurePlugin(LoopAssistantPlugin, {
52
+ app: app.interface.assistant ?? undefined,
53
+ decisions: { serverUrl },
54
+ }),
55
+ ], [app, serverUrl]);
56
+ // The Local agent is the application's: created under its id with its
57
+ // spec, so that the server runs its instructions, its tool and its rule.
58
+ const localAgent = useMemo(() => ({ createPayload: appDatalayerCreatePayload(app) }), [app]);
59
+ return (_jsx(ThemedProvider, { children: _jsxs(Box, { sx: {
60
+ height: '100vh',
61
+ minHeight: 0,
62
+ display: 'flex',
63
+ bg: 'canvas.default',
64
+ }, children: [_jsx(Box, { sx: { flex: 1, minWidth: 0, minHeight: 0 }, children: _jsx(AppRenderer, { app: app, serverUrl: serverUrl, target: "local", localAgent: localAgent, plugins: plugins }) }), _jsxs(Box, { as: "aside", sx: {
65
+ width: 320,
66
+ flexShrink: 0,
67
+ p: 3,
68
+ borderLeft: '1px solid',
69
+ borderColor: 'border.default',
70
+ overflowY: 'auto',
71
+ }, children: [_jsxs(Heading, { as: "h2", sx: { fontSize: 2, mb: 2 }, children: [app.emoji, " Decide"] }), _jsx(Text, { as: "p", sx: { fontSize: 1, mb: 2 }, children: "Typed decisions asked of Jev, the typed-decision model: yes or no with its probability, one of named options, or a score, each with its confidence." }), _jsxs(Text, { as: "p", sx: { fontSize: 1, mb: 2 }, children: [_jsx("strong", { children: "In the chat" }), ": ask \u201CIs this ticket urgent? \u2018Help! My payouts have been failing for 3 days.\u2019\u201D Its agent calls the ", _jsx("code", { children: "decide" }), " tool, a read it does without asking."] }), _jsxs(Text, { as: "p", sx: { fontSize: 1, mb: 2 }, children: [_jsx("strong", { children: "From the assistant" }), ": hover the character below and choose ", _jsx("em", { children: "Ask a decision" }), " \u2014 the situation, the question, and its type. The answer comes back in its balloon."] }), _jsxs(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted' }, children: ["Runs on the local agent-runtimes server at ", serverUrl, ", which asks Jev through ai-inference."] })] })] }) }));
72
+ };
73
+ export default AgentDecideExample;
@@ -51,7 +51,7 @@ const AgentNotificationsInner = ({ onLogout, }) => {
51
51
  protocol: 'ag-ui',
52
52
  agentSpecId: AGENTSPEC_ID,
53
53
  enableSkills: true,
54
- tools: [],
54
+ backendTools: [],
55
55
  },
56
56
  });
57
57
  const [notifications, setNotifications] = useState([]);
@@ -74,7 +74,7 @@ const AgentSkillsInner = ({ onLogout }) => {
74
74
  protocol: 'ag-ui',
75
75
  agentSpecId: AGENTSPEC_ID,
76
76
  enableSkills: true,
77
- tools: [],
77
+ backendTools: [],
78
78
  },
79
79
  });
80
80
  const chatAuthToken = token === null ? undefined : token;
@@ -602,7 +602,7 @@ githubClientId, kaggleToken, }) => {
602
602
  setGoal(spec.goal || '');
603
603
  setSystemPrompt(spec.systemPrompt || spec.goal || DEFAULT_SYSTEM_PROMPT);
604
604
  setSystemPromptCodemodeAddons(spec.systemPromptCodemodeAddons || '');
605
- setTools(spec.tools || []);
605
+ setTools(spec.backendTools || []);
606
606
  setSandboxVariant(spec.sandboxVariant || '');
607
607
  if (spec.model) {
608
608
  setModel(spec.model);
@@ -650,7 +650,7 @@ githubClientId, kaggleToken, }) => {
650
650
  protocol: normalizedProtocol,
651
651
  systemPrompt: systemPrompt || undefined,
652
652
  systemPromptCodemodeAddons: systemPromptCodemodeAddons || undefined,
653
- tools,
653
+ backendTools: tools,
654
654
  sandboxVariant: sandboxVariant || undefined,
655
655
  skills: selectedSkills,
656
656
  mcpServers: selectedMcpServers.map(server => ({
@@ -786,7 +786,7 @@ githubClientId, kaggleToken, }) => {
786
786
  model: model,
787
787
  system_prompt: systemPrompt || DEFAULT_SYSTEM_PROMPT,
788
788
  system_prompt_codemode_addons: systemPromptCodemodeAddons || undefined,
789
- tools: tools,
789
+ backend_tools: tools,
790
790
  sandbox_variant: sandboxVariant || undefined,
791
791
  enable_skills: enableSkills,
792
792
  enable_codemode: enableCodemode,
@@ -98,6 +98,7 @@ export const EXAMPLE_ENTRIES = [
98
98
  makeEntry('AgentCompactionExample', () => import('./AgentCompactionExample'), 'Set a context token budget and watch history compaction summarize older messages, with live from/to token and timing details.', ['example', 'agent', 'compaction', 'context', 'tokens']),
99
99
  makeEntry('AgentCodemodeExample', () => import('./AgentCodemodeExample'), 'Code mode execution and tool orchestration example.'),
100
100
  makeEntry('AgentCodeSandboxesExample', () => import('./AgentCodeSandboxesExample'), 'Launch sandbox-variant agent specs and compare code execution across backends.', ['example', 'agent', 'sandbox', 'codemode']),
101
+ makeEntry('AgentDecideExample', () => import('./AgentDecideExample'), 'Decide: typed decisions asked of Jev — yes or no, a choice, a score — from the chat, where the agent calls decide, and from the floating assistant’s Ask a decision.', ['example', 'agent', 'loop', 'app', 'decisions', 'jev', 'assistant']),
101
102
  makeEntry('AgentEvalsExample', () => import('./AgentEvalsExample'), 'Evaluation workflows for agent outputs.'),
102
103
  makeEntry('AgentGuardrailsExample', () => import('./AgentGuardrailsExample'), 'Guardrails and safety checks for agent runs.'),
103
104
  makeEntry('AgentHooksExample', () => import('./AgentHooksExample'), 'Pre-hooks and post-hooks lifecycle execution example.'),
@@ -25,6 +25,7 @@ export { default as AgentCheckpointsExample } from './AgentCheckpointsExample';
25
25
  export { default as AgentCompactionExample } from './AgentCompactionExample';
26
26
  export { default as AgentCodemodeExample } from './AgentCodemodeExample';
27
27
  export { default as AgentCodeSandboxesExample } from './AgentCodeSandboxesExample';
28
+ export { default as AgentDecideExample } from './AgentDecideExample';
28
29
  export { default as AgentEvalsExample } from './AgentEvalsExample';
29
30
  export { default as AgentGuardrailsExample } from './AgentGuardrailsExample';
30
31
  export { default as AgentHooksExample } from './AgentHooksExample';
@@ -31,6 +31,7 @@ export { default as AgentCheckpointsExample } from './AgentCheckpointsExample';
31
31
  export { default as AgentCompactionExample } from './AgentCompactionExample';
32
32
  export { default as AgentCodemodeExample } from './AgentCodemodeExample';
33
33
  export { default as AgentCodeSandboxesExample } from './AgentCodeSandboxesExample';
34
+ export { default as AgentDecideExample } from './AgentDecideExample';
34
35
  export { default as AgentEvalsExample } from './AgentEvalsExample';
35
36
  export { default as AgentGuardrailsExample } from './AgentGuardrailsExample';
36
37
  export { default as AgentHooksExample } from './AgentHooksExample';
@@ -70,6 +70,9 @@ const ANONYMOUS_EXAMPLES = new Set([
70
70
  // An application beside its computer, on the local agent-runtimes server:
71
71
  // nothing allocated on Datalayer, and the machine itself needs no token.
72
72
  'LoopAppComputerExample',
73
+ // Decide, on the local agent-runtimes server as above: Jev is asked
74
+ // through the server's ai-inference, with the server's own key.
75
+ 'AgentDecideExample',
73
76
  // Runs on the browser sandbox: nothing to allocate, nothing to sign into.
74
77
  'LoopShellExample',
75
78
  // Temporarily anonymous so the Jupyter output surface can be driven and
@@ -89,7 +89,7 @@ export function emptyAppspec(kind = 'chat') {
89
89
  instructions: '',
90
90
  model: '',
91
91
  skills: [],
92
- tools: [],
92
+ backendTools: [],
93
93
  context: [],
94
94
  contents: [],
95
95
  connections: [],
@@ -147,7 +147,7 @@ const KNOWN_KEYS = [
147
147
  'instructions',
148
148
  'model',
149
149
  'skills',
150
- 'tools',
150
+ 'backend_tools',
151
151
  'context',
152
152
  'contents',
153
153
  'connections',
@@ -341,7 +341,7 @@ export function parseAppspec(document) {
341
341
  instructions: text(data.instructions),
342
342
  model: text(data.model),
343
343
  skills: texts(data.skills),
344
- tools: texts(data.tools),
344
+ backendTools: texts(data.backend_tools),
345
345
  context: texts(data.context),
346
346
  contents: texts(data.contents),
347
347
  connections: records(data.connections).map(parseConnection),
@@ -541,7 +541,7 @@ export function dumpAppspec(app) {
541
541
  .text('instructions', app.instructions)
542
542
  .text('model', app.model)
543
543
  .list('skills', app.skills)
544
- .list('tools', app.tools)
544
+ .list('backend_tools', app.backendTools)
545
545
  .list('context', app.context)
546
546
  .list('contents', app.contents)
547
547
  .list('connections', app.connections.map(connection => new Writer()
@@ -36,7 +36,7 @@ import { getModel } from '../../specs/models';
36
36
  import { getNotificationSpec } from '../../specs/notifications';
37
37
  import { getSkillSpec } from '../../specs/skills';
38
38
  import { getTeamSpec } from '../../specs/teams';
39
- import { getToolSpec } from '../../specs/tools';
39
+ import { getBackendToolSpec } from '../../specs/backendTools';
40
40
  import { getTrack } from '../../specs/tracks';
41
41
  import { pluginsOffSetupNotes } from '../plugins/canvas-blocks';
42
42
  import { isAssistantCharacterId, parseAppspec } from './appspec';
@@ -173,8 +173,8 @@ function referenceProblems(app, organizationFrames) {
173
173
  if (!getSkillSpec(idOf(ref)))
174
174
  missing('skill', ref);
175
175
  }
176
- for (const ref of app.tools) {
177
- if (!getToolSpec(idOf(ref)))
176
+ for (const ref of app.backendTools) {
177
+ if (!getBackendToolSpec(idOf(ref)))
178
178
  missing('tool', ref);
179
179
  }
180
180
  for (const ref of app.checks.guards) {
@@ -241,7 +241,7 @@ function referenceProblems(app, organizationFrames) {
241
241
  continue;
242
242
  const [server, name] = splitRef(target);
243
243
  if (server === undefined) {
244
- if (!getToolSpec(name)) {
244
+ if (!getBackendToolSpec(name)) {
245
245
  problems.push(`The rule “${rule.action}” names the tool “${target}”, which the catalogue does not have.`);
246
246
  }
247
247
  continue;
@@ -339,8 +339,8 @@ function setupNotes(app) {
339
339
  }
340
340
  for (const ref of app.skills)
341
341
  note('skill', ref, getSkillSpec(idOf(ref)));
342
- for (const ref of app.tools)
343
- note('tool', ref, getToolSpec(idOf(ref)));
342
+ for (const ref of app.backendTools)
343
+ note('tool', ref, getBackendToolSpec(idOf(ref)));
344
344
  for (const ref of app.checks.guards)
345
345
  note('Guard', ref, own(GUARD_CATALOGUE, idOf(ref)));
346
346
  for (const ref of app.checks.gates)
@@ -34,7 +34,7 @@
34
34
  *
35
35
  * @module loop/apps/rules
36
36
  */
37
- import { SERVER_ACTIONS, TOOL_ACTIONS } from '../../specs/actions';
37
+ import { SERVER_ACTIONS, BACKEND_TOOL_ACTIONS } from '../../specs/actions';
38
38
  /** The four behaviours, from the freest to the most restricted. */
39
39
  export const BEHAVIOURS = [
40
40
  'do_it',
@@ -138,7 +138,7 @@ function entryOf(server, name) {
138
138
  export function classesOf(ref, args) {
139
139
  const [server, name] = splitRef(ref);
140
140
  if (server === undefined) {
141
- return [...(own(TOOL_ACTIONS, name) ?? [])];
141
+ return [...(own(BACKEND_TOOL_ACTIONS, name) ?? [])];
142
142
  }
143
143
  const [classes, conditions] = entryOf(server, name);
144
144
  for (const condition of conditions) {
@@ -9,7 +9,9 @@
9
9
  * while the conversation is out of sight, holds there the approval it waits
10
10
  * on, answered with *Approve* or *Deny* on the path every approval of it is
11
11
  * answered on (T-23, U-19), opens the conversation when clicked, and is
12
- * dragged about and sent away as the chat's own assistant is (T-27).
12
+ * dragged about and sent away as the chat's own assistant is (T-27). Given
13
+ * the runtime to ask (`decisions`), its balloon offers *Ask a decision*: a
14
+ * typed decision asked of Jev through the runtime, answered there.
13
15
  *
14
16
  * The workspace's chat is the conversation: on a page layout, its side panel
15
17
  * is opened and closed; where the conversation is always on screen, a click
@@ -33,6 +35,16 @@ export type LoopAssistantConfig = {
33
35
  * the balloon says an approval waits and the conversation answers it.
34
36
  */
35
37
  appId?: string;
38
+ /**
39
+ * The runtime decisions are asked at — its
40
+ * `/api/v1/configure/inference/decisions`, as the `decide` tool asks — and
41
+ * the token to ask with, if it needs one: the balloon offers *Ask a
42
+ * decision*. Without it, it does not.
43
+ */
44
+ decisions?: {
45
+ serverUrl: string;
46
+ token?: string;
47
+ };
36
48
  };
37
49
  /**
38
50
  * What the character acts out (T-22), from what the application is doing as
@@ -43,6 +55,6 @@ export declare function assistantStateOfTurn(turn: ChatTurnSnapshot, presence: P
43
55
  arriving?: boolean;
44
56
  leaving?: boolean;
45
57
  }): AssistantState;
46
- export declare function LoopAssistant({ app, person, appId, }: LoopAssistantConfig): JSX.Element | null;
58
+ export declare function LoopAssistant({ app, person, appId, decisions, }: LoopAssistantConfig): JSX.Element | null;
47
59
  export declare const LoopAssistantPlugin: import("@datalayer/reactor").ReactorPlugin<LoopAssistantConfig, unknown, unknown>;
48
60
  export default LoopAssistantPlugin;
@@ -7,6 +7,7 @@ import { Box } from '@datalayer/primer-addons';
7
7
  import { useIAMStore } from '@datalayer/core/lib/state/substates/IAMState';
8
8
  import { pageLayoutPanelOpen, togglePagePanel, } from '@datalayer/primer-addons/lib/reactor';
9
9
  import { AssistantStage } from '../../../chat/assistant/AssistantStage';
10
+ import { decisionsAskerAt } from '../../../chat/assistant/decisions';
10
11
  import { ASSISTANT_WORDS, assistantStateOf, keepAway, keptAway, latestSaying, } from '../../../chat/assistant/state';
11
12
  import { useApproveToolRequest, useRejectToolRequest, useToolApprovalsQuery, } from '../../../hooks/useToolApprovals';
12
13
  import { approvalsOfApp, ruleOfApproval } from '../app-rules/AppRulesCard';
@@ -67,7 +68,7 @@ function focusComposer() {
67
68
  const composer = document.querySelector('[data-chat-composer] textarea, [data-chat-composer] [contenteditable="true"]');
68
69
  composer?.focus();
69
70
  }
70
- export function LoopAssistant({ app, person, appId, }) {
71
+ export function LoopAssistant({ app, person, appId, decisions, }) {
71
72
  const contributed = useContributions(LoopAssistantCharacter).map(entry => entry.value);
72
73
  const chosen = assistantCharacterFor(contributed, { app, person });
73
74
  const turnEntries = useContributions(LoopChatTurn);
@@ -110,6 +111,9 @@ export function LoopAssistant({ app, person, appId, }) {
110
111
  }, [open, saying?.id]);
111
112
  const stageRef = useRef(null);
112
113
  const drag = useViewportDrag(stageRef, { whole: true });
114
+ const decide = useMemo(() => decisions?.serverUrl
115
+ ? decisionsAskerAt(decisions.serverUrl, decisions.token)
116
+ : undefined, [decisions?.serverUrl, decisions?.token]);
113
117
  if (away !== 'none') {
114
118
  return null;
115
119
  }
@@ -162,16 +166,21 @@ export function LoopAssistant({ app, person, appId, }) {
162
166
  };
163
167
  return (_jsxs(_Fragment, { children: [appId && signedIn ? (_jsx(WaitingApprovals, { appId: appId, onWaiting: setApproval })) : null, _jsx(AssistantStage, { character: chosen.character, state: state, size: SIZE, place: drag.position
164
168
  ? { left: `${drag.position.left}px`, top: `${drag.position.top}px` }
165
- : { right: '24px', bottom: '24px' }, stageRef: stageRef, onDragStart: drag.onHandlePointerDown, open: open, onToggle: onToggle, balloon: balloon, insist: insist, onDismiss: onDismiss })] }));
169
+ : { right: '24px', bottom: '24px' }, stageRef: stageRef, onDragStart: drag.onHandlePointerDown, open: open, onToggle: onToggle, balloon: balloon, insist: insist, onDismiss: onDismiss, decide: decide })] }));
166
170
  }
167
171
  export const LoopAssistantPlugin = definePlugin({
168
172
  name: LOOP_ASSISTANT_PLUGIN_NAME,
169
- config: { app: undefined, person: undefined, appId: undefined },
173
+ config: {
174
+ app: undefined,
175
+ person: undefined,
176
+ appId: undefined,
177
+ decisions: undefined,
178
+ },
170
179
  displayName: 'Floating assistant',
171
180
  description: 'The chat as a character on the page: the application’s own, or the one the person chose, from the characters the enabled plugins contribute.',
172
181
  octicon: 'paperclip',
173
182
  build: ({ config }) => {
174
- const Configured = () => (_jsx(LoopAssistant, { app: config.app, person: config.person, appId: config.appId }));
183
+ const Configured = () => (_jsx(LoopAssistant, { app: config.app, person: config.person, appId: config.appId, decisions: config.decisions }));
175
184
  return {
176
185
  components: [
177
186
  { id: 'loop-assistant', slot: LoopSlots.root, Component: Configured },
@@ -11,7 +11,7 @@ import type { ActionClass, AppBehaviour, AppEscalation, ServerActionsSpec } from
11
11
  /** The classes of action, from the one that changes nothing. */
12
12
  export declare const ACTION_CLASSES: ActionClass[];
13
13
  /** What each tool of the tools catalogue does, by id. */
14
- export declare const TOOL_ACTIONS: Record<string, ActionClass[]>;
14
+ export declare const BACKEND_TOOL_ACTIONS: Record<string, ActionClass[]>;
15
15
  /**
16
16
  * What each MCP server's tools do, by server id. `checked` is the day the
17
17
  * names were read off the running server; absent when nobody looked.
@@ -12,7 +12,7 @@ export const ACTION_CLASSES = [
12
12
  'publish',
13
13
  ];
14
14
  /** What each tool of the tools catalogue does, by id. */
15
- export const TOOL_ACTIONS = {
15
+ export const BACKEND_TOOL_ACTIONS = {
16
16
  'create-plan': ['read'],
17
17
  'current-time': ['read'],
18
18
  decide: ['read'],