@datalayer/agent-runtimes 1.5.47 → 1.5.48
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.
|
@@ -5,8 +5,9 @@ import type { ApprovalPresentation } from './contracts';
|
|
|
5
5
|
* tool proves that every material argument is shown: each argument the server
|
|
6
6
|
* presented is named by the renderer, or the card fails closed. An unknown
|
|
7
7
|
* tool, an argument the renderer does not know, an attachment, and every
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* action that is not mail (reads, writes, other sends, destructive, financial,
|
|
9
|
+
* publishing, executing) are reviewed in Datalayer (SLACK §15, 5, decided by
|
|
10
|
+
* the user on 16 October 2026: mail only). They render ai-agents' presentation v1, a different input
|
|
10
11
|
* from `../approvals.ts` and `../approvalCard.ts`. Moved from the Slack
|
|
11
12
|
* service (plans/DISCORD.md DC-004).
|
|
12
13
|
*
|
|
@@ -31,8 +32,14 @@ type Renderer = Readonly<{
|
|
|
31
32
|
matches(presentation: ApprovalPresentation): boolean;
|
|
32
33
|
render(presentation: ApprovalPresentation): RenderedAction;
|
|
33
34
|
}>;
|
|
34
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Action classes that are decided in Datalayer only: every class but `send`,
|
|
37
|
+
* since only mail is decided in a host (decided by the user on 16 October
|
|
38
|
+
* 2026, SLACK §15, 5).
|
|
39
|
+
*/
|
|
35
40
|
export declare const DATALAYER_ONLY: Set<"unknown" | "read" | "write" | "send" | "delete" | "publish" | "execute" | "financial">;
|
|
41
|
+
/** The words of a tool's name that make a send mail: contracts.json `mail_words`. */
|
|
42
|
+
export declare const MAIL_WORDS: ReadonlySet<string>;
|
|
36
43
|
/** The renderers, the first that matches wins: Datalayer-only before any other. */
|
|
37
44
|
export declare const RENDERERS: readonly Renderer[];
|
|
38
45
|
/**
|
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Action classes that are decided in Datalayer only: every class but `send`,
|
|
7
|
+
* since only mail is decided in a host (decided by the user on 16 October
|
|
8
|
+
* 2026, SLACK §15, 5).
|
|
9
|
+
*/
|
|
6
10
|
export const DATALAYER_ONLY = new Set([
|
|
11
|
+
'read',
|
|
12
|
+
'write',
|
|
7
13
|
'delete',
|
|
8
14
|
'publish',
|
|
9
15
|
'financial',
|
|
@@ -28,7 +34,19 @@ function rendered(name, presentation, fields, known, extra = []) {
|
|
|
28
34
|
];
|
|
29
35
|
return { complete: reasons.length === 0, fields, reasons, renderer: name };
|
|
30
36
|
}
|
|
31
|
-
|
|
37
|
+
/** The words of a tool's name that make a send mail: contracts.json `mail_words`. */
|
|
38
|
+
export const MAIL_WORDS = new Set([
|
|
39
|
+
'email',
|
|
40
|
+
'gmail',
|
|
41
|
+
'mail',
|
|
42
|
+
]);
|
|
43
|
+
/** A tool name's words, as ai-agents reads them (camelCase and separators split). */
|
|
44
|
+
const wordsOf = (name) => name
|
|
45
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
46
|
+
.toLowerCase()
|
|
47
|
+
.split(/[^a-z0-9]+/)
|
|
48
|
+
.filter(Boolean);
|
|
49
|
+
const isMail = (toolName) => wordsOf(toolName).some(word => MAIL_WORDS.has(word));
|
|
32
50
|
const MAIL_KEYS = [
|
|
33
51
|
'to',
|
|
34
52
|
'cc',
|
|
@@ -42,8 +60,7 @@ const MAIL_KEYS = [
|
|
|
42
60
|
/** Mail: every recipient, the subject, the whole body; an attachment goes to Datalayer. */
|
|
43
61
|
const mail = {
|
|
44
62
|
name: 'mail',
|
|
45
|
-
matches: presentation => presentation.action_class === 'send' &&
|
|
46
|
-
MAIL_TOOL.test(presentation.tool_name),
|
|
63
|
+
matches: presentation => presentation.action_class === 'send' && isMail(presentation.tool_name),
|
|
47
64
|
render(presentation) {
|
|
48
65
|
const args = presentation.arguments;
|
|
49
66
|
const fields = [];
|
|
@@ -82,53 +99,14 @@ const mail = {
|
|
|
82
99
|
return rendered('mail', presentation, fields, MAIL_KEYS, extra);
|
|
83
100
|
},
|
|
84
101
|
};
|
|
85
|
-
|
|
86
|
-
const WRITE_KEYS = [
|
|
87
|
-
'path',
|
|
88
|
-
'file',
|
|
89
|
-
'filename',
|
|
90
|
-
'name',
|
|
91
|
-
'title',
|
|
92
|
-
'content',
|
|
93
|
-
'text',
|
|
94
|
-
'new_path',
|
|
95
|
-
'destination',
|
|
96
|
-
'mode',
|
|
97
|
-
];
|
|
98
|
-
/** A write: where, and the whole of what is written. */
|
|
99
|
-
const write = {
|
|
100
|
-
name: 'write',
|
|
101
|
-
matches: presentation => presentation.action_class === 'write' &&
|
|
102
|
-
WRITE_TOOL.test(presentation.tool_name),
|
|
103
|
-
render(presentation) {
|
|
104
|
-
const args = presentation.arguments;
|
|
105
|
-
const fields = [];
|
|
106
|
-
for (const [key, label] of [
|
|
107
|
-
['path', 'Where'],
|
|
108
|
-
['file', 'Where'],
|
|
109
|
-
['filename', 'Where'],
|
|
110
|
-
['name', 'Name'],
|
|
111
|
-
['title', 'Title'],
|
|
112
|
-
['new_path', 'Moved to'],
|
|
113
|
-
['destination', 'Moved to'],
|
|
114
|
-
['mode', 'How'],
|
|
115
|
-
['content', 'What is written'],
|
|
116
|
-
['text', 'What is written'],
|
|
117
|
-
])
|
|
118
|
-
if (args[key] !== undefined)
|
|
119
|
-
fields.push({ label, value: text(args[key]) });
|
|
120
|
-
const extra = fields.length === 0
|
|
121
|
-
? ['The request does not say what it writes: review it in Datalayer.']
|
|
122
|
-
: [];
|
|
123
|
-
return rendered('write', presentation, fields, WRITE_KEYS, extra);
|
|
124
|
-
},
|
|
125
|
-
};
|
|
126
|
-
/** Delete, publish, money and running code: shown, decided only in Datalayer (§15, 5). */
|
|
102
|
+
/** Everything but mail: shown, decided only in Datalayer (§15, 5). */
|
|
127
103
|
const datalayerOnly = {
|
|
128
104
|
name: 'datalayer-only',
|
|
129
105
|
matches: presentation => DATALAYER_ONLY.has(presentation.action_class),
|
|
130
106
|
render(presentation) {
|
|
131
107
|
const words = {
|
|
108
|
+
read: 'Only mail is decided outside Datalayer: reading is decided in Datalayer.',
|
|
109
|
+
write: 'Only mail is decided outside Datalayer: writing is decided in Datalayer.',
|
|
132
110
|
delete: 'Deleting is decided in Datalayer.',
|
|
133
111
|
execute: 'Running code is decided in Datalayer.',
|
|
134
112
|
financial: 'Moving money is decided in Datalayer.',
|
|
@@ -145,22 +123,8 @@ const datalayerOnly = {
|
|
|
145
123
|
};
|
|
146
124
|
},
|
|
147
125
|
};
|
|
148
|
-
/** A read: every argument, by its name, whole — nothing is changed or sent. */
|
|
149
|
-
const read = {
|
|
150
|
-
name: 'read',
|
|
151
|
-
matches: presentation => presentation.action_class === 'read',
|
|
152
|
-
render(presentation) {
|
|
153
|
-
const fields = Object.entries(presentation.arguments).map(([key, value]) => ({ label: key, value: text(value) }));
|
|
154
|
-
return rendered('read', presentation, fields, Object.keys(presentation.arguments));
|
|
155
|
-
},
|
|
156
|
-
};
|
|
157
126
|
/** The renderers, the first that matches wins: Datalayer-only before any other. */
|
|
158
|
-
export const RENDERERS = [
|
|
159
|
-
datalayerOnly,
|
|
160
|
-
mail,
|
|
161
|
-
write,
|
|
162
|
-
read,
|
|
163
|
-
];
|
|
127
|
+
export const RENDERERS = [datalayerOnly, mail];
|
|
164
128
|
/**
|
|
165
129
|
* How a host shows an approval, by the renderer that knows its tool; with
|
|
166
130
|
* none, nothing is decided in the host.
|
|
@@ -24,7 +24,7 @@ export * from './contracts';
|
|
|
24
24
|
export { DatalayerHostClient, HostRefusedError, type BoundHost, 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 Starter, type StarterSource, type TurnStream, } from './agentClient';
|
|
26
26
|
export { hostSessionUid } from './sessionUid';
|
|
27
|
-
export { DATALAYER_ONLY, RENDERERS, renderApproval, type RenderedAction, type RenderedField, } from './approvalRenderers';
|
|
27
|
+
export { DATALAYER_ONLY, MAIL_WORDS, RENDERERS, renderApproval, type RenderedAction, type RenderedField, } from './approvalRenderers';
|
|
28
28
|
export { DELIVERY_PATH, DELIVERY_ROUTE, DeliveryPoller, deliveryRoute, receiveDelivery, type BoundHostKey, type DeliveryClaimStore, type DeliveryJob, type DeliverySink, } from './deliveries';
|
|
29
29
|
export { TurnState, type TurnEnding, type TurnFile, type TurnTool, } from './turnState';
|
|
30
30
|
export { resolveApplication, usableAllowances, type AllowanceView, type ApplicationRefusal, type ApplicationResolution, type ChannelRule, } from './resolution';
|
|
@@ -29,7 +29,7 @@ export * from './contracts';
|
|
|
29
29
|
export { DatalayerHostClient, HostRefusedError, } from './client';
|
|
30
30
|
export { agUiEventsOf, assertTrustedStreamUrl, DevelopmentCredentials, HostKeyCredentials, hostSessionOf, HostStarters, HttpAgentClient, InstallationCredentials, lastAnswer, } from './agentClient';
|
|
31
31
|
export { hostSessionUid } from './sessionUid';
|
|
32
|
-
export { DATALAYER_ONLY, RENDERERS, renderApproval, } from './approvalRenderers';
|
|
32
|
+
export { DATALAYER_ONLY, MAIL_WORDS, RENDERERS, renderApproval, } from './approvalRenderers';
|
|
33
33
|
export { DELIVERY_PATH, DELIVERY_ROUTE, DeliveryPoller, deliveryRoute, receiveDelivery, } from './deliveries';
|
|
34
34
|
export { TurnState, } from './turnState';
|
|
35
35
|
export { resolveApplication, usableAllowances, } from './resolution';
|