@datalayer/agent-runtimes 1.5.87 → 1.5.89
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/dist-embed/datalayer-app-main.js +22 -9
- package/lib/apps/apps/checks.d.ts +1 -1
- package/lib/apps/apps/checks.js +1 -1
- package/lib/apps/apps/computer.d.ts +1 -1
- package/lib/apps/apps/computer.js +1 -1
- package/lib/apps/apps/pluginPair.d.ts +1 -1
- package/lib/apps/apps/rules.d.ts +1 -1
- package/lib/apps/apps/rules.js +2 -2
- package/lib/apps/apps/visitorToken.d.ts +1 -1
- package/lib/apps/apps/visitorToken.js +1 -1
- package/lib/apps/core/appFiles.js +1 -1
- package/lib/apps/plugins/a2ui-surface/toolResult.d.ts +1 -1
- package/lib/apps/plugins/a2ui-surface/toolResult.js +1 -1
- package/lib/apps/plugins/agent-outputs/sheets.d.ts +76 -0
- package/lib/apps/plugins/agent-outputs/sheets.js +230 -0
- package/lib/apps/plugins/app-page/appPageModel.d.ts +1 -1
- package/lib/apps/plugins/app-page/appPageModel.js +1 -1
- package/lib/chat/messages/ChatMarkdown.d.ts +3 -1
- package/lib/chat/messages/ChatMarkdown.js +4 -1
- package/lib/chat/messages/codeBlocks.d.ts +50 -0
- package/lib/chat/messages/codeBlocks.js +81 -0
- package/lib/examples/AgentOutputsExample.d.ts +7 -0
- package/lib/examples/AgentOutputsExample.js +47 -7
- package/lib/examples/utils/agentOutputsPlugins.d.ts +2 -0
- package/lib/examples/utils/agentOutputsPlugins.js +27 -0
- package/lib/portable/hosts/client.d.ts +11 -1
- package/lib/portable/hosts/client.js +12 -6
- package/lib/portable/hosts/contracts.json +9 -3
- package/lib/portable/hosts/index.d.ts +1 -1
- package/lib/portable/records.d.ts +1 -1
- package/lib/portable/records.js +1 -1
- package/lib/portable/semantic-events.json +3 -3
- package/lib/portable/semanticOfAgUi.d.ts +1 -1
- package/lib/runtimes/variants.d.ts +1 -1
- package/lib/runtimes/variants.js +1 -1
- package/lib/specs/agents/agents.d.ts +1 -0
- package/lib/specs/agents/agents.js +79 -8
- package/lib/specs/apps.js +32 -32
- package/lib/specs/frontendTools.d.ts +1 -0
- package/lib/specs/frontendTools.js +18 -0
- package/lib/specs/harnesses.d.ts +1 -0
- package/lib/specs/harnesses.js +62 -19
- package/lib/specs/index.d.ts +1 -1
- package/lib/specs/index.js +1 -1
- package/lib/specs/mcpServers.js +20 -50
- package/lib/types/mcp.d.ts +4 -2
- package/package.json +2 -1
- package/scripts/codegen/generate_apps.py +1 -1
- package/scripts/codegen/generate_mcp_servers.py +30 -4
- package/scripts/validate_pap_examples.py +1 -1
|
@@ -19,6 +19,13 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
19
19
|
* We subscribe to the chat store, detect the output type of the latest
|
|
20
20
|
* assistant message, auto-switch the sidebar tab, and render the payload
|
|
21
21
|
* inline in the sidebar.
|
|
22
|
+
*
|
|
23
|
+
* A spreadsheet (a ```csv block) is also drawn in the chat message itself, by
|
|
24
|
+
* the `AgentOutputsSheetsPlugin` renderer the chat reads from its
|
|
25
|
+
* `ChatCodeBlock` point; the message's grid and the Sheet tab's are one
|
|
26
|
+
* workbook. The Cells agent tools (`AgentOutputsSheetToolsPlugin`, the
|
|
27
|
+
* `cells` bundle the spec's `frontend_tools` names) act on the last one, so
|
|
28
|
+
* "Chart the spreadsheet" inserts a chart that appears on both grids.
|
|
22
29
|
*/
|
|
23
30
|
/// <reference types="vite/client" />
|
|
24
31
|
import { useEffect, useState, useRef, useMemo } from 'react';
|
|
@@ -26,15 +33,16 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
|
26
33
|
import { Text, Button, Heading, Label } from '@primer/react';
|
|
27
34
|
import { TableIcon, FileIcon, CodeIcon, GraphIcon, DownloadIcon, } from '@primer/octicons-react';
|
|
28
35
|
import { Box } from '@datalayer/primer-addons';
|
|
36
|
+
import { CellsProvider, Spreadsheet } from '@datalayer/cells';
|
|
29
37
|
import { AuthRequiredView } from './components/index.js';
|
|
30
38
|
import { useSimpleAuthStore } from '@datalayer/core/lib/views/otel/index.js';
|
|
31
39
|
import { ThemedProvider } from './utils/themedProvider.js';
|
|
32
40
|
import { uniqueAgentId } from './utils/agentId.js';
|
|
33
41
|
import { LoopEmbed } from '../apps/index.js';
|
|
34
|
-
import {
|
|
42
|
+
import { downloadSheet, parseSheetBlock, useFitHeight, useSheetModel, } from '../apps/plugins/agent-outputs/sheets.js';
|
|
43
|
+
import { AGENT_OUTPUTS_LOOP_PLUGINS } from './utils/agentOutputsPlugins.js';
|
|
35
44
|
import { useChatStore } from '../stores/chatStore.js';
|
|
36
45
|
import { useExampleAgentRuntimesUrl } from './utils/useExampleAgentRuntimesUrl.js';
|
|
37
|
-
const LOOP_PLUGINS_AGENTOUT = [AgentOutputsPlugin];
|
|
38
46
|
const queryClient = new QueryClient();
|
|
39
47
|
// ─── Constants ─────────────────────────────────────────────────────────────
|
|
40
48
|
const AGENT_NAME = 'outputs-example-agent';
|
|
@@ -57,8 +65,6 @@ const expandCompactMarkdownTable = (text) => {
|
|
|
57
65
|
return text.replace(/\|\|/g, '|\n|');
|
|
58
66
|
};
|
|
59
67
|
const EXT_LIKE_INFOS = new Set([
|
|
60
|
-
'csv',
|
|
61
|
-
'tsv',
|
|
62
68
|
'txt',
|
|
63
69
|
'md',
|
|
64
70
|
'markdown',
|
|
@@ -119,6 +125,20 @@ const detectOutput = (m) => {
|
|
|
119
125
|
}
|
|
120
126
|
// File: info string is a known extension OR first line declares a filename.
|
|
121
127
|
const filenameMatch = firstLine.match(/^#\s*filename:\s*([\w.-]+)/i);
|
|
128
|
+
// Spreadsheet: a CSV or TSV, by its fence (`csv`, `tsv`, `spreadsheet`,
|
|
129
|
+
// `cells`) or a `# filename:` ending in .csv or .tsv — read as the chat's
|
|
130
|
+
// renderer reads it, so both grids show the same workbook.
|
|
131
|
+
const sheet = parseSheetBlock(info, rawBody);
|
|
132
|
+
if (sheet) {
|
|
133
|
+
return {
|
|
134
|
+
tab: 'sheet',
|
|
135
|
+
payload: sheet.source,
|
|
136
|
+
filename: sheet.name,
|
|
137
|
+
extension: sheet.extension,
|
|
138
|
+
sheet,
|
|
139
|
+
messageId: m.id,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
122
142
|
if (filenameMatch || EXT_LIKE_INFOS.has(info)) {
|
|
123
143
|
const filename = filenameMatch?.[1] ?? (info ? `output.${info}` : 'output.txt');
|
|
124
144
|
return {
|
|
@@ -257,6 +277,24 @@ const ChartView = ({ source }) => {
|
|
|
257
277
|
}
|
|
258
278
|
return (_jsx(ReactECharts, { option: option, style: { height: 280, width: '100%' } }));
|
|
259
279
|
};
|
|
280
|
+
// ─── Spreadsheet renderer (Datalayer Cells) ───────────────────────────────
|
|
281
|
+
/**
|
|
282
|
+
* A CSV or TSV the agent wrote, in a Datalayer Cells grid: the workbook the
|
|
283
|
+
* chat message shows too (read once, on this thread), editable here, and
|
|
284
|
+
* where the agent's chart goes.
|
|
285
|
+
*/
|
|
286
|
+
const SheetView = ({ block }) => {
|
|
287
|
+
const { model, error } = useSheetModel(block);
|
|
288
|
+
// As tall as its data and charts (up to 640 px), so a chart the agent adds shows.
|
|
289
|
+
const height = useFitHeight(model, 200, 640);
|
|
290
|
+
if (error) {
|
|
291
|
+
return (_jsxs(Text, { sx: { color: 'danger.fg', fontSize: 0 }, children: ["Could not read the spreadsheet: ", error] }));
|
|
292
|
+
}
|
|
293
|
+
if (!model) {
|
|
294
|
+
return _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: "Reading\u2026" });
|
|
295
|
+
}
|
|
296
|
+
return (_jsx(CellsProvider, { model: model, children: _jsx(Box, { height: height, border: "1px solid", borderColor: "border.muted", children: _jsx(Spreadsheet, { model: model, "aria-label": block.name }) }) }));
|
|
297
|
+
};
|
|
260
298
|
// ─── Inner component (rendered after auth) ─────────────────────────────────
|
|
261
299
|
const AgentOutputsInner = () => {
|
|
262
300
|
// The Loop creates the agent from the plugin's blueprint when it connects;
|
|
@@ -312,10 +350,11 @@ const AgentOutputsInner = () => {
|
|
|
312
350
|
document.body.removeChild(a);
|
|
313
351
|
URL.revokeObjectURL(url);
|
|
314
352
|
};
|
|
315
|
-
return (_jsxs(Box, { height: "100%", display: "flex", flexDirection: "column", children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, px: 3, py: 2, borderBottom: "1px solid", borderColor: "border.default", flexShrink: 0, children: [_jsx(TableIcon, { size: 16 }), _jsx(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: "Agent Outputs \u2014 Local Runtime" })] }), _jsxs(Box, { flex: 1, minHeight: 0, display: "flex", children: [_jsx(Box, { flex: 1, minWidth: 0, children: _jsx(LoopEmbed, { serverUrl: agentBaseUrl, target: "local", showAgentVariants: true, agentId: agentName, editors: false, showHeader: true, plugins:
|
|
353
|
+
return (_jsxs(Box, { height: "100%", display: "flex", flexDirection: "column", children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, px: 3, py: 2, borderBottom: "1px solid", borderColor: "border.default", flexShrink: 0, children: [_jsx(TableIcon, { size: 16 }), _jsx(Heading, { as: "h3", sx: { fontSize: 2, flex: 1 }, children: "Agent Outputs \u2014 Local Runtime" })] }), _jsxs(Box, { flex: 1, minHeight: 0, display: "flex", children: [_jsx(Box, { flex: 1, minWidth: 0, children: _jsx(LoopEmbed, { serverUrl: agentBaseUrl, target: "local", showAgentVariants: true, agentId: agentName, editors: false, showHeader: true, plugins: AGENT_OUTPUTS_LOOP_PLUGINS }) }), _jsxs(Box, { width: 420, borderLeft: "1px solid", borderColor: "border.default", display: "flex", flexDirection: "column", overflow: "hidden", children: [_jsx(Box, { display: "flex", borderBottom: "1px solid", borderColor: "border.default", flexShrink: 0, children: [
|
|
316
354
|
{ key: 'table', icon: TableIcon, label: 'Table' },
|
|
317
355
|
{ key: 'json', icon: CodeIcon, label: 'JSON' },
|
|
318
356
|
{ key: 'chart', icon: GraphIcon, label: 'Chart' },
|
|
357
|
+
{ key: 'sheet', icon: TableIcon, label: 'Sheet' },
|
|
319
358
|
{ key: 'files', icon: FileIcon, label: 'Files' },
|
|
320
359
|
].map(t => {
|
|
321
360
|
const n = countByTab(t.key);
|
|
@@ -328,14 +367,15 @@ const AgentOutputsInner = () => {
|
|
|
328
367
|
borderColor: activeTab === t.key ? 'accent.fg' : 'transparent',
|
|
329
368
|
fontWeight: activeTab === t.key ? 'bold' : 'normal',
|
|
330
369
|
}, children: [t.label, n > 0 ? ` (${n})` : ''] }, t.key));
|
|
331
|
-
}) }), _jsxs(Box, { p: 3, flex: 1, overflow: "auto", children: [_jsxs(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: [activeTab.charAt(0).toUpperCase() + activeTab.slice(1), " outputs"] }), filtered.length === 0 ? (_jsxs(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: ["No ", activeTab, " outputs yet. Use one of the openers in the chat to produce one \u2014 the side panel will switch to the matching tab automatically."
|
|
370
|
+
}) }), _jsxs(Box, { p: 3, flex: 1, overflow: "auto", children: [_jsxs(Heading, { as: "h4", sx: { fontSize: 1, mb: 2 }, children: [activeTab.charAt(0).toUpperCase() + activeTab.slice(1), " outputs"] }), filtered.length === 0 ? (_jsxs(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: ["No ", activeTab, " outputs yet. Use one of the openers in the chat to produce one \u2014 the side panel will switch to the matching tab automatically.", activeTab === 'sheet' &&
|
|
371
|
+
' For a spreadsheet, ask for the data as CSV, for example: "Give me twelve months of sales by region as a CSV".'] })) : (filtered.map((d, idx) => (_jsxs(Box, { p: 2, mb: 2, border: "1px solid", borderColor: "border.default", borderRadius: 2, children: [_jsxs(Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 2, gap: 2, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: d.filename ?? `${d.tab} output` }), _jsx(Label, { size: "small", variant: "secondary", children: d.tab })] }), d.tab === 'table' && _jsx(MarkdownTable, { source: d.payload }), d.tab === 'json' && (_jsx(Box, { as: "pre", bg: "canvas.default", p: 2, borderRadius: 2, fontFamily: "mono", fontSize: 0, maxHeight: 320, overflow: "auto", whiteSpace: "pre-wrap", m: 0, children: (() => {
|
|
332
372
|
try {
|
|
333
373
|
return JSON.stringify(JSON.parse(d.payload), null, 2);
|
|
334
374
|
}
|
|
335
375
|
catch {
|
|
336
376
|
return d.payload;
|
|
337
377
|
}
|
|
338
|
-
})() })), d.tab === 'chart' && _jsx(ChartView, { source: d.payload }), d.tab === 'files' && (_jsxs(_Fragment, { children: [_jsx(Box, { as: "pre", bg: "canvas.default", p: 2, borderRadius: 2, fontFamily: "mono", fontSize: 0, maxHeight: 200, overflow: "auto", whiteSpace: "pre-wrap", m: 0, mb: 2, children: d.payload }), _jsxs(Button, { size: "small", leadingVisual: DownloadIcon, onClick: () => download(d), children: ["Download ", d.filename ?? 'file'] })] }))] }, d.messageId + ':' + idx))))] })] })] })] }));
|
|
378
|
+
})() })), d.tab === 'chart' && _jsx(ChartView, { source: d.payload }), d.tab === 'sheet' && d.sheet && (_jsxs(_Fragment, { children: [_jsx(SheetView, { block: d.sheet }), _jsx(Box, { mt: 2, children: _jsxs(Button, { size: "small", leadingVisual: DownloadIcon, onClick: () => downloadSheet(d.sheet), children: ["Download ", d.filename ?? 'spreadsheet'] }) })] })), d.tab === 'files' && (_jsxs(_Fragment, { children: [_jsx(Box, { as: "pre", bg: "canvas.default", p: 2, borderRadius: 2, fontFamily: "mono", fontSize: 0, maxHeight: 200, overflow: "auto", whiteSpace: "pre-wrap", m: 0, mb: 2, children: d.payload }), _jsxs(Button, { size: "small", leadingVisual: DownloadIcon, onClick: () => download(d), children: ["Download ", d.filename ?? 'file'] })] }))] }, d.messageId + ':' + idx))))] })] })] })] }));
|
|
339
379
|
};
|
|
340
380
|
// ─── Sync token to core IAM store ──────────────────────────────────────────
|
|
341
381
|
const syncTokenToIamStore = (token) => {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The Loop plugins of the outputs example (`AgentOutputsExample`): the
|
|
7
|
+
* `example-output` agent, the chat's spreadsheet renderer, and the Cells
|
|
8
|
+
* agent tools on the last spreadsheet answered. The agent runs on a server,
|
|
9
|
+
* so the page names the bundle whose tools it hands it — `cells`, the grid's
|
|
10
|
+
* tools, run on this page's reactor — through the chat extras.
|
|
11
|
+
*
|
|
12
|
+
* Apart from the page, so a test reads the list without mounting the Loop.
|
|
13
|
+
*
|
|
14
|
+
* @module examples/utils/agentOutputsPlugins
|
|
15
|
+
*/
|
|
16
|
+
import { AgentOutputsPlugin } from '../../apps/plugins/agent-outputs/index.js';
|
|
17
|
+
import { AgentOutputsSheetsPlugin, AgentOutputsSheetToolsPlugin, } from '../../apps/plugins/agent-outputs/sheets.js';
|
|
18
|
+
import { createChatExtrasPlugin } from '../../apps/plugins/chat-extras/index.js';
|
|
19
|
+
const SHEET_EXTRAS = createChatExtrasPlugin();
|
|
20
|
+
SHEET_EXTRAS.setExtras({ agentToolBundles: ['cells'] });
|
|
21
|
+
/** The Loop's plugins on the outputs page: the agent, the chat's grids, the grid's tools. */
|
|
22
|
+
export const AGENT_OUTPUTS_LOOP_PLUGINS = [
|
|
23
|
+
AgentOutputsPlugin,
|
|
24
|
+
AgentOutputsSheetsPlugin,
|
|
25
|
+
AgentOutputsSheetToolsPlugin,
|
|
26
|
+
SHEET_EXTRAS.plugin,
|
|
27
|
+
];
|
|
@@ -35,16 +35,26 @@ export type BoundHost = Readonly<{
|
|
|
35
35
|
* with its key in `X-Datalayer-Host-Key`, or as a person, with the host token
|
|
36
36
|
* the exchange answered. Any host speaks them.
|
|
37
37
|
*/
|
|
38
|
+
/** Which app a host runs as: Datalayer's own, or one the person brought (`custom`). */
|
|
39
|
+
export type HostProvider = 'datalayer' | 'custom';
|
|
38
40
|
export declare class DatalayerHostClient {
|
|
39
41
|
#private;
|
|
40
42
|
readonly apiUrl: string;
|
|
41
43
|
readonly fetchImplementation: typeof fetch;
|
|
42
44
|
constructor(apiUrl: string, fetchImplementation?: typeof fetch);
|
|
43
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Bind the installation its owner set up, with the code their browser
|
|
47
|
+
* carried, asserting the app this host runs as: `datalayer` for
|
|
48
|
+
* Datalayer's own app, `custom` with the app's id for one the person
|
|
49
|
+
* brought. Datalayer refuses a provider that is not the one the
|
|
50
|
+
* installation was registered for (409), and a bind without one (422).
|
|
51
|
+
*/
|
|
44
52
|
bind(input: {
|
|
45
53
|
code: string;
|
|
46
54
|
externalId: string;
|
|
47
55
|
name?: string;
|
|
56
|
+
provider: HostProvider;
|
|
57
|
+
customAppId?: string;
|
|
48
58
|
}): Promise<BoundHost>;
|
|
49
59
|
/** The installation was removed from its host: it ends at Datalayer (revocation). */
|
|
50
60
|
uninstalled(hostKey: string): Promise<void>;
|
|
@@ -21,11 +21,6 @@ export class HostRefusedError extends Error {
|
|
|
21
21
|
this.what = what;
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
/**
|
|
25
|
-
* The generic host routes of ai-agents a host calls besides the credential exchange: as the installation,
|
|
26
|
-
* with its key in `X-Datalayer-Host-Key`, or as a person, with the host token
|
|
27
|
-
* the exchange answered. Any host speaks them.
|
|
28
|
-
*/
|
|
29
24
|
export class DatalayerHostClient {
|
|
30
25
|
apiUrl;
|
|
31
26
|
fetchImplementation;
|
|
@@ -54,13 +49,24 @@ export class DatalayerHostClient {
|
|
|
54
49
|
throw new HostRefusedError(response.status, typeof body.detail === 'string' ? body.detail : 'refused', what);
|
|
55
50
|
return schema.parse(body);
|
|
56
51
|
}
|
|
57
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Bind the installation its owner set up, with the code their browser
|
|
54
|
+
* carried, asserting the app this host runs as: `datalayer` for
|
|
55
|
+
* Datalayer's own app, `custom` with the app's id for one the person
|
|
56
|
+
* brought. Datalayer refuses a provider that is not the one the
|
|
57
|
+
* installation was registered for (409), and a bind without one (422).
|
|
58
|
+
*/
|
|
58
59
|
async bind(input) {
|
|
60
|
+
if (input.provider === 'custom' && !input.customAppId) {
|
|
61
|
+
throw new Error("A custom app's bind names its app id (customAppId): Datalayer refuses it otherwise.");
|
|
62
|
+
}
|
|
59
63
|
const bound = await this.#call('Datalayer did not bind the installation', '/apps/hosts/bind', {
|
|
60
64
|
body: {
|
|
61
65
|
code: input.code,
|
|
62
66
|
external_id: input.externalId,
|
|
63
67
|
name: input.name ?? '',
|
|
68
|
+
provider: input.provider,
|
|
69
|
+
custom_app_id: input.provider === 'custom' ? (input.customAppId ?? '') : '',
|
|
64
70
|
},
|
|
65
71
|
method: 'POST',
|
|
66
72
|
}, bindSchema);
|
|
@@ -36,7 +36,9 @@
|
|
|
36
36
|
"request": {
|
|
37
37
|
"code": "dlhc_…",
|
|
38
38
|
"external_id": "A0123:-:T0123",
|
|
39
|
-
"name": "Acme"
|
|
39
|
+
"name": "Acme",
|
|
40
|
+
"provider": "datalayer",
|
|
41
|
+
"custom_app_id": ""
|
|
40
42
|
},
|
|
41
43
|
"response_keys": [
|
|
42
44
|
"success",
|
|
@@ -452,7 +454,9 @@
|
|
|
452
454
|
"bind_request": {
|
|
453
455
|
"code": "dlhc_…",
|
|
454
456
|
"external_id": "123456789012345678:234567890123456789",
|
|
455
|
-
"name": "Acme"
|
|
457
|
+
"name": "Acme",
|
|
458
|
+
"provider": "datalayer",
|
|
459
|
+
"custom_app_id": ""
|
|
456
460
|
},
|
|
457
461
|
"external_user_id": "567890123456789012",
|
|
458
462
|
"thread": {
|
|
@@ -501,7 +505,9 @@
|
|
|
501
505
|
"bind_request": {
|
|
502
506
|
"code": "dlhc_…",
|
|
503
507
|
"external_id": "102290129340398:106540352242922",
|
|
504
|
-
"name": "Acme"
|
|
508
|
+
"name": "Acme",
|
|
509
|
+
"provider": "custom",
|
|
510
|
+
"custom_app_id": "1234567890"
|
|
505
511
|
},
|
|
506
512
|
"external_user_id": "US.13491208655302741918",
|
|
507
513
|
"external_user_name": "Alice",
|
|
@@ -21,7 +21,7 @@ export { AgUiFrames, readRunStream, type AgUiEvent } from '../agui';
|
|
|
21
21
|
export * from '../semantic';
|
|
22
22
|
export { askQuestionOf, semanticOf, turnOf, type TurnInfo, } from '../semanticOfAgUi';
|
|
23
23
|
export * from './contracts';
|
|
24
|
-
export { DatalayerHostClient, HostRefusedError, type BoundHost, type HostSelf, } from './client';
|
|
24
|
+
export { DatalayerHostClient, HostRefusedError, type BoundHost, type HostProvider, type HostSelf, } from './client';
|
|
25
25
|
export { agUiEventsOf, assertTrustedStreamUrl, DevelopmentCredentials, HostKeyCredentials, hostSessionOf, HostStarters, HttpAgentClient, InstallationCredentials, lastAnswer, type AgentClient, type HostCredentials, type HostKeyLookup, type HostSession, type HostShape, type HostTurnRequest, type Place, type SessionBinder, type Starter, type StarterSource, type TurnProvenance, type TurnStream, } from './agentClient';
|
|
26
26
|
export { hostSessionUid } from './sessionUid';
|
|
27
27
|
export { DATALAYER_ONLY, MAIL_WORDS, RENDERERS, renderApproval, type RenderedAction, type RenderedField, } from './approvalRenderers';
|
|
@@ -15,7 +15,7 @@ export declare const RUN_END_WORDS: Record<string, string>;
|
|
|
15
15
|
/**
|
|
16
16
|
* The mark around what the runtime tells an application of a turn a personal
|
|
17
17
|
* agent asked over PAP or PACT, before the request (`asked_for_said`,
|
|
18
|
-
* `ASKED_FOR_TAG` in agent_runtimes.
|
|
18
|
+
* `ASKED_FOR_TAG` in agent_runtimes.apps.pap_company).
|
|
19
19
|
*/
|
|
20
20
|
export declare const ASKED_FOR_TAG = "asked-for";
|
|
21
21
|
/**
|
package/lib/portable/records.js
CHANGED
|
@@ -23,7 +23,7 @@ export const RUN_END_WORDS = {
|
|
|
23
23
|
/**
|
|
24
24
|
* The mark around what the runtime tells an application of a turn a personal
|
|
25
25
|
* agent asked over PAP or PACT, before the request (`asked_for_said`,
|
|
26
|
-
* `ASKED_FOR_TAG` in agent_runtimes.
|
|
26
|
+
* `ASKED_FOR_TAG` in agent_runtimes.apps.pap_company).
|
|
27
27
|
*/
|
|
28
28
|
export const ASKED_FOR_TAG = 'asked-for';
|
|
29
29
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"about": "The semantic agent events a chat host renders (Slack, Discord: DC-005, S-004, S-205), and the AG-UI events of agent-runtimes' session API (agent_runtimes/routes/apps.py, agent_runtimes/
|
|
3
|
+
"about": "The semantic agent events a chat host renders (Slack, Discord: DC-005, S-004, S-205), and the AG-UI events of agent-runtimes' session API (agent_runtimes/routes/apps.py, agent_runtimes/apps/sessions.py, agent_runtimes/apps/external_turns.py) each reduces to. src/portable/semanticOfAgUi.ts reduces every case (src/portable/__tests__/semantic.unit.test.ts); agent_runtimes/tests/test_semantic_events_contract.py holds the cases to what the runtime emits.",
|
|
4
4
|
"kinds": [
|
|
5
5
|
"text",
|
|
6
6
|
"progress",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"table": "a Markdown table in the answer (src/portable/semantic.ts answerParts); no AG-UI event carries one",
|
|
24
24
|
"file": "none in agent-runtimes 1.5.45: reserved, rendered as a safe HTTPS link when produced",
|
|
25
25
|
"citation": "an HTTPS Markdown link in the answer (answerParts); no AG-UI event carries one",
|
|
26
|
-
"ask": "AG-UI RUN_FINISHED with result.asking (agent_runtimes/
|
|
26
|
+
"ask": "AG-UI RUN_FINISHED with result.asking (agent_runtimes/apps/sessions.py question_of); the run stream carries no loop.ask event",
|
|
27
27
|
"completion": "AG-UI RUN_FINISHED without asking",
|
|
28
|
-
"stop": "the host itself, after its own Stop: a stopped session's stream ends without RUN_FINISHED or RUN_ERROR (agent_runtimes/
|
|
28
|
+
"stop": "the host itself, after its own Stop: a stopped session's stream ends without RUN_FINISHED or RUN_ERROR (agent_runtimes/apps/sessions.py stop, _close); no AG-UI event carries it",
|
|
29
29
|
"error": "AG-UI RUN_ERROR message",
|
|
30
30
|
"sign-in": "AG-UI TOOL_CALL_RESULT of pap_sign_in (or pact_sign_in, with or without a gateway prefix) whose result is a sign-in waiting for the person with an https page (src/portable/signIn.ts readPapSignIn), after the tool's complete row; a page that is not https gives the row only"
|
|
31
31
|
},
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* `readRunStream` (`agui.ts`); this says what each event means to a host.
|
|
5
5
|
*
|
|
6
6
|
* The runtime's `loop.turn` event says which turn a stream is and where it
|
|
7
|
-
* stands (`running`, `finished`, `failed`: agent_runtimes/
|
|
7
|
+
* stands (`running`, `finished`, `failed`: agent_runtimes/apps/
|
|
8
8
|
* external_turns.py); a stopped session's stream ends without a run end,
|
|
9
9
|
* so `stop` is never read from an event: the host that pressed Stop says it.
|
|
10
10
|
* A question is read from `RUN_FINISHED.result.asking` only: the run stream
|
|
@@ -37,7 +37,7 @@ export declare const CUSTOM_HARNESS = "custom";
|
|
|
37
37
|
* when one does.
|
|
38
38
|
*
|
|
39
39
|
* A harness the catalogue offers (`agentspecs/harnesses`, SH-01) — Claude
|
|
40
|
-
* Code, Codex, OpenCode,
|
|
40
|
+
* Code, Codex, OpenCode, pi — is served by the Datalayer runtime
|
|
41
41
|
* through its ACP adapter (`ACPAgent`, SH-10): the runtime launches the
|
|
42
42
|
* harness as its subprocess, so the runtime's locations run it and the
|
|
43
43
|
* browser, which has no process to launch, does not. Three are refused:
|
package/lib/runtimes/variants.js
CHANGED
|
@@ -73,7 +73,7 @@ export const CUSTOM_HARNESS = 'custom';
|
|
|
73
73
|
* when one does.
|
|
74
74
|
*
|
|
75
75
|
* A harness the catalogue offers (`agentspecs/harnesses`, SH-01) — Claude
|
|
76
|
-
* Code, Codex, OpenCode,
|
|
76
|
+
* Code, Codex, OpenCode, pi — is served by the Datalayer runtime
|
|
77
77
|
* through its ACP adapter (`ACPAgent`, SH-10): the runtime launches the
|
|
78
78
|
* harness as its subprocess, so the runtime's locations run it and the
|
|
79
79
|
* browser, which has no process to launch, does not. Three are refused:
|
|
@@ -48,6 +48,7 @@ export declare const EXAMPLE_HARNESS_GEMINI_CLI_AGENTSPEC_0_0_1: Agentspec;
|
|
|
48
48
|
export declare const EXAMPLE_HARNESS_GOOSE_AGENTSPEC_0_0_1: Agentspec;
|
|
49
49
|
export declare const EXAMPLE_HARNESS_OPENCODE_AGENTSPEC_0_0_1: Agentspec;
|
|
50
50
|
export declare const EXAMPLE_HARNESS_OPENHANDS_AGENTSPEC_0_0_1: Agentspec;
|
|
51
|
+
export declare const EXAMPLE_HARNESS_PI_AGENTSPEC_0_0_1: Agentspec;
|
|
51
52
|
export declare const EXAMPLE_HOOKS_AGENTSPEC_0_0_1: Agentspec;
|
|
52
53
|
export declare const EXAMPLE_HUMAN_APPROVED_AUTOMATION_AGENTSPEC_0_0_1: Agentspec;
|
|
53
54
|
export declare const EXAMPLE_HUMAN_IN_THE_LOOP_AGENTSPEC_0_0_1: Agentspec;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { ALPHAVANTAGE_MCP_SERVER_0_0_1, CHART_MCP_SERVER_0_0_1, EARTHDATA_MCP_SERVER_0_0_1, EURUS_MCP_SERVER_0_0_1, FILESYSTEM_MCP_SERVER_0_0_1, GITHUB_MCP_SERVER_0_0_1, GOOGLE_WORKSPACE_MCP_SERVER_0_0_1, HUGGINGFACE_MCP_SERVER_0_0_1, KAGGLE_MCP_SERVER_0_0_1, ODOO_MCP_SERVER_0_0_1, SALESFORCE_MCP_SERVER_0_0_1, SLACK_MCP_SERVER_0_0_1, TAVILY_MCP_SERVER_0_0_1, } from '../mcpServers.js';
|
|
6
6
|
import { ACCOUNTING_SKILL_SPEC_0_0_1, CRAWL_SKILL_SPEC_0_0_1, EVENTS_SKILL_SPEC_0_0_1, GITHUB_SKILL_SPEC_0_0_1, JOKES_SKILL_SPEC_0_0_1, PDF_SKILL_SPEC_0_0_1, TEXT_SUMMARIZER_SKILL_SPEC_0_0_1, } from '../skills.js';
|
|
7
7
|
import { DECIDE_BACKEND_TOOL_SPEC_0_0_1, EXAMPLE_CREATE_PLAN_BACKEND_TOOL_SPEC_0_0_1, EXAMPLE_CURRENT_TIME_BACKEND_TOOL_SPEC_0_0_1, EXAMPLE_DISPLAY_RECIPE_BACKEND_TOOL_SPEC_0_0_1, EXAMPLE_GENERATE_HAIKU_BACKEND_TOOL_SPEC_0_0_1, EXAMPLE_GENERATE_TASK_STEPS_BACKEND_TOOL_SPEC_0_0_1, EXAMPLE_GET_WEATHER_BACKEND_TOOL_SPEC_0_0_1, EXAMPLE_RENDER_A2UI_SURFACE_BACKEND_TOOL_SPEC_0_0_1, EXAMPLE_UPDATE_PLAN_STEP_BACKEND_TOOL_SPEC_0_0_1, RUNTIME_ECHO_BACKEND_TOOL_SPEC_0_0_1, RUNTIME_SEND_MAIL_BACKEND_TOOL_SPEC_0_0_1, RUNTIME_SENSITIVE_ECHO_BACKEND_TOOL_SPEC_0_0_1, } from '../backendTools.js';
|
|
8
|
-
import { DECKS_FRONTEND_TOOL_SPEC_0_0_1, JUPYTER_NOTEBOOK_EDIT_FRONTEND_TOOL_SPEC_0_0_1, JUPYTER_NOTEBOOK_PROPOSE_FRONTEND_TOOL_SPEC_0_0_1, JUPYTER_NOTEBOOK_READ_FRONTEND_TOOL_SPEC_0_0_1, JUPYTER_NOTEBOOK_FRONTEND_TOOL_SPEC_0_0_1, LEXICAL_DOCUMENT_FRONTEND_TOOL_SPEC_0_0_1, } from '../frontendTools.js';
|
|
8
|
+
import { CELLS_FRONTEND_TOOL_SPEC_0_0_1, DECKS_FRONTEND_TOOL_SPEC_0_0_1, JUPYTER_NOTEBOOK_EDIT_FRONTEND_TOOL_SPEC_0_0_1, JUPYTER_NOTEBOOK_PROPOSE_FRONTEND_TOOL_SPEC_0_0_1, JUPYTER_NOTEBOOK_READ_FRONTEND_TOOL_SPEC_0_0_1, JUPYTER_NOTEBOOK_FRONTEND_TOOL_SPEC_0_0_1, LEXICAL_DOCUMENT_FRONTEND_TOOL_SPEC_0_0_1, } from '../frontendTools.js';
|
|
9
9
|
// ============================================================================
|
|
10
10
|
// MCP Server Lookup
|
|
11
11
|
// ============================================================================
|
|
@@ -100,6 +100,8 @@ const TOOL_MAP = {
|
|
|
100
100
|
* Map frontend tool IDs to FrontendToolSpec objects.
|
|
101
101
|
*/
|
|
102
102
|
const FRONTEND_TOOL_MAP = {
|
|
103
|
+
'cells:0.0.1': CELLS_FRONTEND_TOOL_SPEC_0_0_1,
|
|
104
|
+
cells: CELLS_FRONTEND_TOOL_SPEC_0_0_1,
|
|
103
105
|
'decks:0.0.1': DECKS_FRONTEND_TOOL_SPEC_0_0_1,
|
|
104
106
|
decks: DECKS_FRONTEND_TOOL_SPEC_0_0_1,
|
|
105
107
|
'jupyter-notebook-edit:0.0.1': JUPYTER_NOTEBOOK_EDIT_FRONTEND_TOOL_SPEC_0_0_1,
|
|
@@ -2918,6 +2920,54 @@ export const EXAMPLE_HARNESS_OPENHANDS_AGENTSPEC_0_0_1 = {
|
|
|
2918
2920
|
parameters: undefined,
|
|
2919
2921
|
subagents: undefined,
|
|
2920
2922
|
};
|
|
2923
|
+
export const EXAMPLE_HARNESS_PI_AGENTSPEC_0_0_1 = {
|
|
2924
|
+
id: 'example-harness-pi',
|
|
2925
|
+
version: '0.0.1',
|
|
2926
|
+
name: 'A pi Agent',
|
|
2927
|
+
description: `pi as a Datalayer agent: launched in the runtime over the Agent Client Protocol, its files, terminals and permissions decided by the Shield under the application's Rules, every action in the record. Needs the account's ANTHROPIC_API_KEY.`,
|
|
2928
|
+
tags: ['coding', 'harness', 'acp'],
|
|
2929
|
+
domain: undefined,
|
|
2930
|
+
enabled: false,
|
|
2931
|
+
model: undefined,
|
|
2932
|
+
mcpServers: [],
|
|
2933
|
+
skills: [].filter(Boolean),
|
|
2934
|
+
backendTools: [],
|
|
2935
|
+
frontendTools: [],
|
|
2936
|
+
environmentName: 'ai-agents-env',
|
|
2937
|
+
icon: undefined,
|
|
2938
|
+
emoji: undefined,
|
|
2939
|
+
color: undefined,
|
|
2940
|
+
suggestions: [],
|
|
2941
|
+
welcomeMessage: undefined,
|
|
2942
|
+
welcomeNotebook: undefined,
|
|
2943
|
+
welcomeDocument: undefined,
|
|
2944
|
+
sandboxVariant: 'jupyter-server',
|
|
2945
|
+
harness: 'pi',
|
|
2946
|
+
systemPrompt: undefined,
|
|
2947
|
+
systemPromptCodemodeAddons: undefined,
|
|
2948
|
+
goal: undefined,
|
|
2949
|
+
delegable: [],
|
|
2950
|
+
protocol: undefined,
|
|
2951
|
+
ui: [],
|
|
2952
|
+
protocols: [],
|
|
2953
|
+
trigger: undefined,
|
|
2954
|
+
modelConfig: undefined,
|
|
2955
|
+
mcpServerTools: undefined,
|
|
2956
|
+
guardrails: undefined,
|
|
2957
|
+
evals: undefined,
|
|
2958
|
+
codemode: undefined,
|
|
2959
|
+
output: undefined,
|
|
2960
|
+
advanced: undefined,
|
|
2961
|
+
checkpoints: undefined,
|
|
2962
|
+
authorizationPolicy: undefined,
|
|
2963
|
+
notifications: undefined,
|
|
2964
|
+
memory: 'ephemeral',
|
|
2965
|
+
preHooks: undefined,
|
|
2966
|
+
postHooks: undefined,
|
|
2967
|
+
toolHooks: undefined,
|
|
2968
|
+
parameters: undefined,
|
|
2969
|
+
subagents: undefined,
|
|
2970
|
+
};
|
|
2921
2971
|
export const EXAMPLE_HOOKS_AGENTSPEC_0_0_1 = {
|
|
2922
2972
|
id: 'example-hooks',
|
|
2923
2973
|
version: '0.0.1',
|
|
@@ -3949,7 +3999,7 @@ export const EXAMPLE_OUTPUT_AGENTSPEC_0_0_1 = {
|
|
|
3949
3999
|
id: 'example-output',
|
|
3950
4000
|
version: '0.0.1',
|
|
3951
4001
|
name: 'Example Output Agent',
|
|
3952
|
-
description: `Demonstrates structured response rendering (table, json, chart, and file) for the AgentOutputsExample side panel, which detects the block in each answer and renders it.`,
|
|
4002
|
+
description: `Demonstrates structured response rendering (table, json, chart, spreadsheet and file) for the AgentOutputsExample side panel, which detects the block in each answer and renders it; a spreadsheet is drawn with Datalayer Cells, in the chat and in the panel, and charted on the grid through the Cells frontend tools.`,
|
|
3953
4003
|
tags: ['workflow', 'visualization', 'automation'],
|
|
3954
4004
|
domain: undefined,
|
|
3955
4005
|
enabled: false,
|
|
@@ -3958,7 +4008,7 @@ export const EXAMPLE_OUTPUT_AGENTSPEC_0_0_1 = {
|
|
|
3958
4008
|
skills: [].filter(Boolean),
|
|
3959
4009
|
backendTools: [],
|
|
3960
4010
|
disableToolApprovals: true,
|
|
3961
|
-
frontendTools: [],
|
|
4011
|
+
frontendTools: [FRONTEND_TOOL_MAP['cells:0.0.1']],
|
|
3962
4012
|
environmentName: 'ai-agents-env',
|
|
3963
4013
|
icon: 'table',
|
|
3964
4014
|
emoji: '📦',
|
|
@@ -3977,23 +4027,43 @@ export const EXAMPLE_OUTPUT_AGENTSPEC_0_0_1 = {
|
|
|
3977
4027
|
summary: 'Sales chart',
|
|
3978
4028
|
},
|
|
3979
4029
|
{
|
|
3980
|
-
text: '
|
|
3981
|
-
summary: '
|
|
4030
|
+
text: 'Give me a spreadsheet of twelve months of sales by region (North, South, Online), with a Month column, as one ```csv fenced block whose first line is `# filename: sales.csv`.',
|
|
4031
|
+
summary: 'Sales spreadsheet',
|
|
4032
|
+
},
|
|
4033
|
+
{
|
|
4034
|
+
text: 'Chart the sales spreadsheet: a column chart of the three regions by month, titled Sales by region, inserted on the grid below the data.',
|
|
4035
|
+
summary: 'Chart the spreadsheet',
|
|
4036
|
+
},
|
|
4037
|
+
{
|
|
4038
|
+
text: 'Create a YAML file named config.yaml for a small web service (name, port, log level and two routes), in a ```yaml fenced block whose first line is `# filename: config.yaml`.',
|
|
4039
|
+
summary: 'YAML file',
|
|
3982
4040
|
},
|
|
3983
4041
|
],
|
|
3984
|
-
welcomeMessage: 'Example output agent ready. Ask for a TABLE, JSON, a CHART or a FILE and I will answer with exactly one structured output block.',
|
|
4042
|
+
welcomeMessage: 'Example output agent ready. Ask for a TABLE, JSON, a CHART, a SPREADSHEET or a FILE and I will answer with exactly one structured output block; once a spreadsheet is shown, ask me to chart it on its grid.',
|
|
3985
4043
|
welcomeNotebook: undefined,
|
|
3986
4044
|
welcomeDocument: undefined,
|
|
3987
4045
|
sandboxVariant: 'jupyter-server',
|
|
3988
4046
|
harness: 'pydantic-ai',
|
|
3989
4047
|
systemPrompt: `You are the Example Output Agent.
|
|
3990
|
-
The user may request one of exactly
|
|
4048
|
+
The user may request one of exactly six output modes: TABLE, JSON, CHART, SPREADSHEET, FILE or SHEET CHART. For the first five, emit exactly one mode and nothing else: no prose before or after the block. Answer from what you know: do not run code or call tools to produce the block.
|
|
3991
4049
|
Formatting rules: - TABLE: Return one GitHub-flavored markdown table, one row per line,
|
|
3992
4050
|
never several rows joined on a single line.
|
|
3993
4051
|
- JSON: Return exactly one fenced \`\`\`json code block. - CHART: Return exactly one fenced \`\`\`json code block whose first line is
|
|
3994
4052
|
"// chart" and whose remaining body is valid ECharts option JSON.
|
|
4053
|
+
- SPREADSHEET: Return exactly one fenced \`\`\`csv code block whose first
|
|
4054
|
+
line is "# filename: <name>.csv", then a header row, then one row per
|
|
4055
|
+
line, comma-separated, numbers without thousands separators or units.
|
|
3995
4056
|
- FILE: Return exactly one fenced code block whose info string is a file
|
|
3996
|
-
extension, and whose first line is
|
|
4057
|
+
extension other than csv or tsv, and whose first line is
|
|
4058
|
+
"# filename: <name.ext>".
|
|
4059
|
+
- SHEET CHART: when asked to chart, plot or graph the spreadsheet already
|
|
4060
|
+
shown (the last SPREADSHEET answer), do not write a block: work on the
|
|
4061
|
+
grid with the Cells tools. Call cells_read_range with no range to find
|
|
4062
|
+
the data, then cells_insert_chart over that range (headers included) with
|
|
4063
|
+
the type and title asked for, at the first column two rows below the
|
|
4064
|
+
data (for data in A1:D13, at A15), unless told where. Answer in one short
|
|
4065
|
+
sentence naming the chart and its range. If the tools say no grid is
|
|
4066
|
+
shown, ask for the spreadsheet first.
|
|
3997
4067
|
|
|
3998
4068
|
If mode is ambiguous, default to JSON.`,
|
|
3999
4069
|
systemPromptCodemodeAddons: undefined,
|
|
@@ -13858,6 +13928,7 @@ export const AGENTSPECS = {
|
|
|
13858
13928
|
'example-harness-goose': EXAMPLE_HARNESS_GOOSE_AGENTSPEC_0_0_1,
|
|
13859
13929
|
'example-harness-opencode': EXAMPLE_HARNESS_OPENCODE_AGENTSPEC_0_0_1,
|
|
13860
13930
|
'example-harness-openhands': EXAMPLE_HARNESS_OPENHANDS_AGENTSPEC_0_0_1,
|
|
13931
|
+
'example-harness-pi': EXAMPLE_HARNESS_PI_AGENTSPEC_0_0_1,
|
|
13861
13932
|
'example-hooks': EXAMPLE_HOOKS_AGENTSPEC_0_0_1,
|
|
13862
13933
|
'example-human-approved-automation': EXAMPLE_HUMAN_APPROVED_AUTOMATION_AGENTSPEC_0_0_1,
|
|
13863
13934
|
'example-human-in-the-loop': EXAMPLE_HUMAN_IN_THE_LOOP_AGENTSPEC_0_0_1,
|