@agentshouse/mdruntime-adapter 0.1.0-alpha.8 → 0.1.0-c6229cc476473
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/AGENTS.md +157 -26
- package/README.md +32 -0
- package/dist/actions.d.ts +4 -12
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +239 -332
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +259 -194
- package/dist/digest.js +1 -5
- package/dist/discovery.d.ts +20 -18
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +182 -210
- package/dist/gather.d.ts +3 -0
- package/dist/gather.d.ts.map +1 -0
- package/dist/gather.js +40 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/links.d.ts +12 -0
- package/dist/links.d.ts.map +1 -0
- package/dist/links.js +66 -0
- package/dist/map.d.ts +2 -2
- package/dist/map.d.ts.map +1 -1
- package/dist/map.js +6 -7
- package/dist/model.d.ts +2 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +21 -39
- package/dist/read.d.ts +29 -23
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +222 -195
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +30 -51
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +110 -124
- package/dist/stream.d.ts +11 -5
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +211 -213
- package/dist/transport.d.ts +46 -28
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +3 -3
- package/dist/version.d.ts +1 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +23 -18
- package/dist/write.d.ts +9 -3
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +123 -196
- package/package.json +4 -12
- package/dist/actions.js.map +0 -1
- package/dist/adapter.js.map +0 -1
- package/dist/digest.js.map +0 -1
- package/dist/discovery.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/map.js.map +0 -1
- package/dist/model.js.map +0 -1
- package/dist/read.js.map +0 -1
- package/dist/refusal.js.map +0 -1
- package/dist/site.js.map +0 -1
- package/dist/stream.js.map +0 -1
- package/dist/transport.js.map +0 -1
- package/dist/version.js.map +0 -1
- package/dist/write.js.map +0 -1
package/dist/actions.js
CHANGED
|
@@ -1,121 +1,59 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { changeBatchIdentity } from '@agentshouse/mdruntime';
|
|
1
|
+
import { changeBatchIdentity, } from '@agentshouse/mdruntime';
|
|
3
2
|
import { doorRefusal } from './refusal.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
'conversation.send',
|
|
8
|
-
'conversation.answer',
|
|
9
|
-
'conversation.interrupt',
|
|
10
|
-
'conversation.kill',
|
|
11
|
-
'conversation.cancel',
|
|
12
|
-
'conversation.delete',
|
|
13
|
-
'conversation.history'
|
|
14
|
-
];
|
|
15
|
-
export const HOUSE_ACTS = [
|
|
16
|
-
'conversations/interaction/read',
|
|
17
|
-
'conversations/originals/read',
|
|
18
|
-
'apps/read',
|
|
19
|
-
'apps/customize',
|
|
20
|
-
'rooms/read',
|
|
21
|
-
'rooms/access/read',
|
|
22
|
-
'rooms/access/invitations',
|
|
23
|
-
'rooms/access/entries',
|
|
24
|
-
'rooms/access/invite',
|
|
25
|
-
'rooms/access/invitation-cancel',
|
|
26
|
-
'rooms/access/revoke',
|
|
27
|
-
'rooms/access/leave',
|
|
28
|
-
'rooms/roles/define',
|
|
29
|
-
'rooms/roles/remove',
|
|
30
|
-
'rooms/roles/assign',
|
|
31
|
-
'rooms/roles/unassign',
|
|
32
|
-
'rooms/settings/processing/read',
|
|
33
|
-
'rooms/settings/processing/write',
|
|
34
|
-
'profiles/create',
|
|
35
|
-
'profiles/read',
|
|
36
|
-
'profiles/edit',
|
|
37
|
-
'profiles/duplicate',
|
|
38
|
-
'profiles/delegate',
|
|
39
|
-
'agents/create',
|
|
40
|
-
'agents/read',
|
|
41
|
-
'routines/requests',
|
|
42
|
-
'routines/access',
|
|
43
|
-
'routines/owned',
|
|
44
|
-
'routines/granted',
|
|
45
|
-
'routines/grant',
|
|
46
|
-
'routines/send',
|
|
47
|
-
'routines/cancel',
|
|
48
|
-
'routines/start',
|
|
49
|
-
'routines/schedules',
|
|
50
|
-
'routines/schedules/create',
|
|
51
|
-
'routines/schedules/enabled',
|
|
52
|
-
'account/security/read',
|
|
53
|
-
'storage/inventory',
|
|
54
|
-
'storage/usage',
|
|
55
|
-
'usage/statement',
|
|
56
|
-
'storage/blob-store',
|
|
57
|
-
'storage/blob-store/select',
|
|
58
|
-
'storage/connections',
|
|
59
|
-
'storage/archive',
|
|
60
|
-
'storage/archive/status',
|
|
61
|
-
'environments/read',
|
|
62
|
-
'environments/create',
|
|
63
|
-
'environments/start',
|
|
64
|
-
'environments/stop',
|
|
65
|
-
'environments/delete',
|
|
66
|
-
'environments/renewals/read',
|
|
67
|
-
'environments/work/read',
|
|
68
|
-
'nodes/read'
|
|
69
|
-
];
|
|
70
|
-
export const HOUSE_PROVIDER_ACTIONS = [
|
|
71
|
-
...CONVERSATION_ACTIONS,
|
|
72
|
-
...HOUSE_ACTS
|
|
73
|
-
];
|
|
74
|
-
const DECLARED = new Set(HOUSE_PROVIDER_ACTIONS);
|
|
75
|
-
export const HISTORY_PAGE = 100;
|
|
3
|
+
import { PRIVATE_LOCATOR } from './transport.js';
|
|
4
|
+
const HISTORY_PAGE = 100;
|
|
5
|
+
const HISTORY_CONVERSATIONS = 64;
|
|
76
6
|
const OCTET_STREAM = 'application/octet-stream';
|
|
77
|
-
const CONVERSATION_ROUTES =
|
|
78
|
-
'conversation.create'
|
|
79
|
-
'conversation.send'
|
|
80
|
-
'conversation.answer'
|
|
81
|
-
'conversation.interrupt'
|
|
82
|
-
'conversation.kill'
|
|
83
|
-
'conversation.
|
|
84
|
-
'conversation.
|
|
85
|
-
|
|
86
|
-
'conversations/interaction/read': '/door/conversations/interaction/read',
|
|
87
|
-
'conversations/originals/read': '/door/conversations/originals/read'
|
|
88
|
-
};
|
|
7
|
+
const CONVERSATION_ROUTES = new Map([
|
|
8
|
+
['conversation.create', '/door/conversations/create'],
|
|
9
|
+
['conversation.send', '/door/conversations/send'],
|
|
10
|
+
['conversation.answer', '/door/conversations/interaction/answer'],
|
|
11
|
+
['conversation.interrupt', '/door/conversations/interrupt'],
|
|
12
|
+
['conversation.kill', '/door/conversations/kill'],
|
|
13
|
+
['conversation.delete', '/door/conversations/delete'],
|
|
14
|
+
['conversation.history', '/door/conversations/history'],
|
|
15
|
+
]);
|
|
89
16
|
export const HOUSE_CONVERSATION_CARDS = {
|
|
90
|
-
locator:
|
|
91
|
-
type: 'conversation',
|
|
17
|
+
locator: PRIVATE_LOCATOR,
|
|
18
|
+
type: 'house-conversation',
|
|
92
19
|
identity: 'conversation',
|
|
93
|
-
agent: 'agent'
|
|
20
|
+
agent: 'agent',
|
|
94
21
|
};
|
|
95
|
-
export function declaredActions() {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
22
|
+
export function declaredActions(routes) {
|
|
23
|
+
const mapped = new Map([...CONVERSATION_ROUTES].map(([name, route]) => [route.slice('/door/'.length), name]));
|
|
24
|
+
return routes.map((route) => ({
|
|
25
|
+
name: mapped.get(route) ?? route,
|
|
26
|
+
inputShape: {},
|
|
27
|
+
resultKind: 'house',
|
|
28
|
+
}));
|
|
101
29
|
}
|
|
102
30
|
export function houseAction(transport, request) {
|
|
103
|
-
if (
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return carry(transport, request.name, request.input);
|
|
31
|
+
if (request.name === 'conversation.send')
|
|
32
|
+
return sendAction(transport, request.input);
|
|
33
|
+
if (request.name === 'conversation.history')
|
|
34
|
+
return historyAction(transport, request.input);
|
|
35
|
+
if (request.name === 'attachments/upload')
|
|
36
|
+
return attachAction(transport, request.input);
|
|
37
|
+
if (request.name === 'attachments/get')
|
|
38
|
+
return openAction(transport, request.input);
|
|
39
|
+
const route = routeOf(request.name);
|
|
40
|
+
if (route === null)
|
|
41
|
+
return Promise.resolve(malformed());
|
|
42
|
+
return carry(transport, route, request.name, request.input);
|
|
116
43
|
}
|
|
117
44
|
function routeOf(name) {
|
|
118
|
-
|
|
45
|
+
const mapped = CONVERSATION_ROUTES.get(name);
|
|
46
|
+
if (mapped !== undefined)
|
|
47
|
+
return mapped;
|
|
48
|
+
const parts = name.split('/');
|
|
49
|
+
if (parts.some((part) => part === '.' || part === '..'))
|
|
50
|
+
return null;
|
|
51
|
+
try {
|
|
52
|
+
return `/door/${parts.map(encodeURIComponent).join('/')}`;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
119
57
|
}
|
|
120
58
|
function record(value) {
|
|
121
59
|
return typeof value === 'object' && value !== null ? value : {};
|
|
@@ -128,31 +66,16 @@ function operationId(input) {
|
|
|
128
66
|
return text(input, 'operation_id') ?? changeBatchIdentity();
|
|
129
67
|
}
|
|
130
68
|
function malformed() {
|
|
131
|
-
return {
|
|
132
|
-
kind: 'rejected',
|
|
133
|
-
code: 'invalid_request',
|
|
134
|
-
fields: {}
|
|
135
|
-
};
|
|
69
|
+
return { kind: 'rejected', code: 'invalid_request', fields: {} };
|
|
136
70
|
}
|
|
137
71
|
function bodyOf(name, input) {
|
|
138
72
|
if (name === 'conversation.create') {
|
|
139
|
-
return {
|
|
140
|
-
agent_id: text(input, 'agent_id'),
|
|
141
|
-
operation_id: operationId(input)
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
if (name === 'conversation.interrupt' || name === 'conversation.kill' || name === 'conversation.delete') {
|
|
145
|
-
return {
|
|
146
|
-
conversation_id: text(input, 'conversation'),
|
|
147
|
-
operation_id: operationId(input)
|
|
148
|
-
};
|
|
73
|
+
return { agent_id: text(input, 'agent_id'), operation_id: operationId(input) };
|
|
149
74
|
}
|
|
150
|
-
if (name === 'conversation.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
operation_id: operationId(input)
|
|
155
|
-
};
|
|
75
|
+
if (name === 'conversation.interrupt' ||
|
|
76
|
+
name === 'conversation.kill' ||
|
|
77
|
+
name === 'conversation.delete') {
|
|
78
|
+
return { conversation_id: text(input, 'conversation'), operation_id: operationId(input) };
|
|
156
79
|
}
|
|
157
80
|
if (name === 'conversation.answer') {
|
|
158
81
|
const nested = record(record(input).answer);
|
|
@@ -160,8 +83,7 @@ function bodyOf(name, input) {
|
|
|
160
83
|
conversation_id: text(input, 'conversation'),
|
|
161
84
|
operation_id: operationId(input),
|
|
162
85
|
interaction_id: text(nested, 'interaction_id'),
|
|
163
|
-
|
|
164
|
-
response: nested.response
|
|
86
|
+
response: nested.response,
|
|
165
87
|
};
|
|
166
88
|
}
|
|
167
89
|
return input;
|
|
@@ -169,37 +91,25 @@ function bodyOf(name, input) {
|
|
|
169
91
|
function withTurn(body) {
|
|
170
92
|
const held = record(body);
|
|
171
93
|
const turn = text(held, 'message_id');
|
|
172
|
-
return turn === undefined ? body : {
|
|
173
|
-
...held,
|
|
174
|
-
turn
|
|
175
|
-
};
|
|
94
|
+
return turn === undefined ? body : { ...held, turn };
|
|
176
95
|
}
|
|
177
96
|
export function actionOutcome(answer, name) {
|
|
178
|
-
if (answer.status === 401)
|
|
179
|
-
kind: 'revoked-authorization'
|
|
180
|
-
};
|
|
97
|
+
if (answer.status === 401)
|
|
98
|
+
return { kind: 'revoked-authorization' };
|
|
181
99
|
const refusal = doorRefusal(answer.body);
|
|
182
100
|
if (refusal !== null) {
|
|
183
|
-
return {
|
|
184
|
-
kind: 'rejected',
|
|
185
|
-
code: refusal.code,
|
|
186
|
-
fields: refusal.fields
|
|
187
|
-
};
|
|
101
|
+
return { kind: 'rejected', code: refusal.code, fields: refusal.fields };
|
|
188
102
|
}
|
|
189
|
-
if (answer.status ===
|
|
190
|
-
kind: '
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
result: withTurn(answer.body)
|
|
195
|
-
};
|
|
196
|
-
return {
|
|
197
|
-
kind: 'action',
|
|
198
|
-
result: answer.body
|
|
199
|
-
};
|
|
103
|
+
if (answer.status === 404)
|
|
104
|
+
return { kind: 'rejected', code: 'action-unimplemented', fields: { name } };
|
|
105
|
+
if (answer.status === 0 || answer.status >= 400)
|
|
106
|
+
return { kind: 'transport-uncertainty' };
|
|
107
|
+
if (name === 'conversation.send')
|
|
108
|
+
return { kind: 'action', result: withTurn(answer.body) };
|
|
109
|
+
return { kind: 'action', result: answer.body };
|
|
200
110
|
}
|
|
201
|
-
async function carry(transport, name, input) {
|
|
202
|
-
const answer = await transport.door(
|
|
111
|
+
async function carry(transport, route, name, input) {
|
|
112
|
+
const answer = await transport.door(route, bodyOf(name, input));
|
|
203
113
|
return actionOutcome(answer, name);
|
|
204
114
|
}
|
|
205
115
|
function sendFile(entry) {
|
|
@@ -207,7 +117,8 @@ function sendFile(entry) {
|
|
|
207
117
|
const name = text(file, 'name');
|
|
208
118
|
const bytes = file.byteLength;
|
|
209
119
|
const sha256 = text(file, 'contentHash');
|
|
210
|
-
if (name === undefined || typeof bytes !== 'number' || sha256 === undefined)
|
|
120
|
+
if (name === undefined || typeof bytes !== 'number' || sha256 === undefined)
|
|
121
|
+
return null;
|
|
211
122
|
const mediaType = text(file, 'mediaType');
|
|
212
123
|
const width = file.width;
|
|
213
124
|
const height = file.height;
|
|
@@ -216,239 +127,235 @@ function sendFile(entry) {
|
|
|
216
127
|
media_type: mediaType !== undefined && mediaType.length > 0 ? mediaType : OCTET_STREAM,
|
|
217
128
|
bytes,
|
|
218
129
|
sha256,
|
|
219
|
-
...typeof width === 'number' && typeof height === 'number'
|
|
220
|
-
dimensions: {
|
|
221
|
-
|
|
222
|
-
height
|
|
223
|
-
}
|
|
224
|
-
} : {}
|
|
130
|
+
...(typeof width === 'number' && typeof height === 'number'
|
|
131
|
+
? { dimensions: { width, height } }
|
|
132
|
+
: {}),
|
|
225
133
|
};
|
|
226
134
|
}
|
|
227
135
|
function sendFiles(input) {
|
|
228
136
|
const files = record(input).files;
|
|
229
|
-
if (files === undefined)
|
|
230
|
-
|
|
137
|
+
if (files === undefined)
|
|
138
|
+
return [];
|
|
139
|
+
if (!Array.isArray(files))
|
|
140
|
+
return null;
|
|
231
141
|
const declared = [];
|
|
232
|
-
for (const entry of files){
|
|
142
|
+
for (const entry of files) {
|
|
233
143
|
const file = sendFile(entry);
|
|
234
|
-
if (file === null)
|
|
144
|
+
if (file === null)
|
|
145
|
+
return null;
|
|
235
146
|
declared.push(file);
|
|
236
147
|
}
|
|
237
148
|
return declared;
|
|
238
149
|
}
|
|
239
150
|
function sendBody(input) {
|
|
240
151
|
const files = sendFiles(input);
|
|
241
|
-
if (files === null)
|
|
152
|
+
if (files === null)
|
|
153
|
+
return null;
|
|
242
154
|
const textValue = text(input, 'text');
|
|
243
155
|
return {
|
|
244
156
|
conversation_id: text(input, 'conversation'),
|
|
245
157
|
operation_id: operationId(input),
|
|
246
|
-
...textValue !== undefined && textValue.length > 0 ? {
|
|
247
|
-
|
|
248
|
-
} : {},
|
|
249
|
-
...files.length === 0 ? {} : {
|
|
250
|
-
files
|
|
251
|
-
}
|
|
158
|
+
...(textValue !== undefined && textValue.length > 0 ? { text: textValue } : {}),
|
|
159
|
+
...(files.length === 0 ? {} : { files }),
|
|
252
160
|
};
|
|
253
161
|
}
|
|
254
162
|
async function fileBytes(file) {
|
|
255
163
|
const blob = record(file).blob;
|
|
256
|
-
if (blob === undefined || typeof blob !== 'object' || blob === null)
|
|
257
|
-
|
|
164
|
+
if (blob === undefined || typeof blob !== 'object' || blob === null)
|
|
165
|
+
return null;
|
|
166
|
+
if (!('arrayBuffer' in blob) || typeof blob.arrayBuffer !== 'function')
|
|
167
|
+
return null;
|
|
258
168
|
return new Uint8Array(await blob.arrayBuffer());
|
|
259
169
|
}
|
|
170
|
+
function delivered(answer, name) {
|
|
171
|
+
return answer.status === 200 ? null : actionOutcome(answer, name);
|
|
172
|
+
}
|
|
260
173
|
function uploadGrant(entry) {
|
|
261
|
-
if (!('upload' in record(entry)))
|
|
174
|
+
if (!('upload' in record(entry)))
|
|
175
|
+
return 'absent';
|
|
262
176
|
const upload = record(record(entry).upload);
|
|
263
|
-
if (upload.method !== 'POST')
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
url: upload.url
|
|
269
|
-
};
|
|
177
|
+
if (upload.method !== 'POST')
|
|
178
|
+
return null;
|
|
179
|
+
if (typeof upload.operation !== 'string' || typeof upload.url !== 'string')
|
|
180
|
+
return null;
|
|
181
|
+
return { method: 'POST', operation: upload.operation, url: upload.url };
|
|
270
182
|
}
|
|
271
183
|
async function uploadOriginals(transport, input, result) {
|
|
272
184
|
const originals = record(result).originals;
|
|
273
|
-
if (!Array.isArray(originals) || originals.length === 0)
|
|
185
|
+
if (!Array.isArray(originals) || originals.length === 0)
|
|
186
|
+
return null;
|
|
274
187
|
const files = Array.isArray(record(input).files) ? record(input).files : [];
|
|
275
|
-
for (const [index, entry] of originals.entries()){
|
|
188
|
+
for (const [index, entry] of originals.entries()) {
|
|
276
189
|
const grant = uploadGrant(entry);
|
|
277
|
-
if (grant === 'absent')
|
|
278
|
-
|
|
190
|
+
if (grant === 'absent')
|
|
191
|
+
continue;
|
|
192
|
+
if (grant === null)
|
|
193
|
+
return malformed();
|
|
279
194
|
const bytes = index < files.length ? await fileBytes(files[index]) : null;
|
|
280
195
|
if (bytes === null) {
|
|
281
|
-
return {
|
|
282
|
-
kind: 'rejected',
|
|
283
|
-
code: 'conversation_original_descriptor_required',
|
|
284
|
-
fields: {}
|
|
285
|
-
};
|
|
196
|
+
return { kind: 'rejected', code: 'conversation_original_descriptor_required', fields: {} };
|
|
286
197
|
}
|
|
287
|
-
const
|
|
198
|
+
const failed = delivered(await transport.transfer({
|
|
288
199
|
act: 'conversation_original_upload',
|
|
289
200
|
method: 'POST',
|
|
290
201
|
url: grant.url,
|
|
202
|
+
answer: 'json',
|
|
291
203
|
body: bytes,
|
|
292
|
-
operation: grant.operation
|
|
293
|
-
});
|
|
294
|
-
if (
|
|
295
|
-
|
|
204
|
+
operation: grant.operation,
|
|
205
|
+
}), 'conversation.send');
|
|
206
|
+
if (failed !== null)
|
|
207
|
+
return failed;
|
|
296
208
|
}
|
|
297
209
|
return null;
|
|
298
210
|
}
|
|
211
|
+
async function attachAction(transport, input) {
|
|
212
|
+
const { blob, ...descriptor } = record(input);
|
|
213
|
+
const bytes = await fileBytes({ blob });
|
|
214
|
+
if (bytes === null)
|
|
215
|
+
return malformed();
|
|
216
|
+
const answer = await transport.door('/door/attachments/upload', descriptor);
|
|
217
|
+
const outcome = actionOutcome(answer, 'attachments/upload');
|
|
218
|
+
if (outcome.kind !== 'action')
|
|
219
|
+
return outcome;
|
|
220
|
+
const grant = uploadGrant(outcome.result);
|
|
221
|
+
if (grant === 'absent')
|
|
222
|
+
return outcome;
|
|
223
|
+
if (grant === null)
|
|
224
|
+
return malformed();
|
|
225
|
+
const stored = await transport.transfer({
|
|
226
|
+
act: 'original_upload',
|
|
227
|
+
method: 'POST',
|
|
228
|
+
url: grant.url,
|
|
229
|
+
answer: 'json',
|
|
230
|
+
body: bytes,
|
|
231
|
+
operation: grant.operation,
|
|
232
|
+
});
|
|
233
|
+
return delivered(stored, 'attachments/upload') ?? { kind: 'action', result: stored.body };
|
|
234
|
+
}
|
|
235
|
+
async function openAction(transport, input) {
|
|
236
|
+
const answer = await transport.door('/door/attachments/get', input);
|
|
237
|
+
const outcome = actionOutcome(answer, 'attachments/get');
|
|
238
|
+
if (outcome.kind !== 'action')
|
|
239
|
+
return outcome;
|
|
240
|
+
const { download, ...opened } = record(outcome.result);
|
|
241
|
+
if (download === undefined)
|
|
242
|
+
return outcome;
|
|
243
|
+
const grant = record(download);
|
|
244
|
+
if (grant.method !== 'GET' || typeof grant.url !== 'string')
|
|
245
|
+
return malformed();
|
|
246
|
+
const read = await transport.transfer({
|
|
247
|
+
act: 'original_download',
|
|
248
|
+
method: 'GET',
|
|
249
|
+
url: grant.url,
|
|
250
|
+
answer: 'bytes',
|
|
251
|
+
});
|
|
252
|
+
const failed = delivered(read, 'attachments/get');
|
|
253
|
+
if (failed !== null)
|
|
254
|
+
return failed;
|
|
255
|
+
if (!(read.body instanceof Blob))
|
|
256
|
+
return { kind: 'transport-uncertainty' };
|
|
257
|
+
return { kind: 'action', result: { ...opened, blob: read.body } };
|
|
258
|
+
}
|
|
299
259
|
async function sendAction(transport, input) {
|
|
300
260
|
const body = sendBody(input);
|
|
301
|
-
if (body === null)
|
|
261
|
+
if (body === null)
|
|
262
|
+
return malformed();
|
|
302
263
|
const answer = await transport.door('/door/conversations/send', body);
|
|
303
264
|
const outcome = actionOutcome(answer, 'conversation.send');
|
|
304
|
-
if (outcome.kind !== 'action')
|
|
265
|
+
if (outcome.kind !== 'action')
|
|
266
|
+
return outcome;
|
|
305
267
|
const uploaded = await uploadOriginals(transport, input, outcome.result);
|
|
306
|
-
if (uploaded !== null)
|
|
268
|
+
if (uploaded !== null)
|
|
269
|
+
return uploaded;
|
|
307
270
|
return outcome;
|
|
308
271
|
}
|
|
309
272
|
function historyCursor(value) {
|
|
310
|
-
|
|
273
|
+
const acceptedAt = text(value, 'accepted_at');
|
|
274
|
+
const messageId = text(value, 'message_id');
|
|
275
|
+
if (acceptedAt === undefined || messageId === undefined)
|
|
276
|
+
return null;
|
|
277
|
+
return { accepted_at: acceptedAt, message_id: messageId };
|
|
278
|
+
}
|
|
279
|
+
function position(cursor) {
|
|
280
|
+
return JSON.stringify({ accepted_at: cursor.accepted_at, message_id: cursor.message_id });
|
|
281
|
+
}
|
|
282
|
+
function positionCursor(value) {
|
|
311
283
|
try {
|
|
312
|
-
|
|
313
|
-
}
|
|
284
|
+
return historyCursor(JSON.parse(value));
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
314
287
|
return null;
|
|
315
288
|
}
|
|
316
|
-
const acceptedAt = text(parsed, 'accepted_at');
|
|
317
|
-
const messageId = text(parsed, 'message_id');
|
|
318
|
-
if (acceptedAt === undefined || messageId === undefined) return null;
|
|
319
|
-
return {
|
|
320
|
-
accepted_at: acceptedAt,
|
|
321
|
-
message_id: messageId
|
|
322
|
-
};
|
|
323
289
|
}
|
|
324
|
-
function
|
|
325
|
-
const
|
|
326
|
-
if (
|
|
290
|
+
export function acceptedMessage(entry) {
|
|
291
|
+
const cursor = historyCursor(entry);
|
|
292
|
+
if (cursor === null)
|
|
293
|
+
return null;
|
|
327
294
|
return {
|
|
328
|
-
|
|
329
|
-
|
|
295
|
+
identity: cursor.message_id,
|
|
296
|
+
turn: text(entry, 'turn_id') ?? cursor.message_id,
|
|
297
|
+
position: position(cursor),
|
|
298
|
+
text: text(entry, 'text') ?? '',
|
|
299
|
+
message: structuredClone(entry),
|
|
330
300
|
};
|
|
331
301
|
}
|
|
332
|
-
function
|
|
333
|
-
const
|
|
334
|
-
const
|
|
335
|
-
if (
|
|
336
|
-
|
|
337
|
-
accepted_at: acceptedAt,
|
|
338
|
-
message_id: messageId
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
export async function readConversationHistory(transport, conversationId) {
|
|
302
|
+
function historyPage(entry) {
|
|
303
|
+
const held = record(entry);
|
|
304
|
+
const conversation = text(held, 'conversation_id');
|
|
305
|
+
if (conversation === undefined || !Array.isArray(held.messages))
|
|
306
|
+
return null;
|
|
342
307
|
const messages = [];
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
after
|
|
349
|
-
},
|
|
350
|
-
limit: HISTORY_PAGE
|
|
351
|
-
});
|
|
352
|
-
const outcome = actionOutcome(answer, 'conversation.history');
|
|
353
|
-
if (outcome.kind !== 'action') return {
|
|
354
|
-
outcome
|
|
355
|
-
};
|
|
356
|
-
const held = record(outcome.result);
|
|
357
|
-
if (!Array.isArray(held.messages)) return {
|
|
358
|
-
outcome: {
|
|
359
|
-
kind: 'transport-uncertainty'
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
for (const entry of held.messages){
|
|
363
|
-
if (text(entry, 'message_id') === undefined) {
|
|
364
|
-
return {
|
|
365
|
-
outcome: {
|
|
366
|
-
kind: 'transport-uncertainty'
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
messages.push(entry);
|
|
371
|
-
}
|
|
372
|
-
if (held.next === null || held.next === undefined) return {
|
|
373
|
-
messages
|
|
374
|
-
};
|
|
375
|
-
const next = record(held.next);
|
|
376
|
-
const acceptedAt = text(next, 'accepted_at');
|
|
377
|
-
const messageId = text(next, 'message_id');
|
|
378
|
-
if (acceptedAt === undefined || messageId === undefined) {
|
|
379
|
-
return {
|
|
380
|
-
outcome: {
|
|
381
|
-
kind: 'transport-uncertainty'
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
after = {
|
|
386
|
-
accepted_at: acceptedAt,
|
|
387
|
-
message_id: messageId
|
|
388
|
-
};
|
|
308
|
+
for (const one of held.messages) {
|
|
309
|
+
const message = acceptedMessage(one);
|
|
310
|
+
if (message === null)
|
|
311
|
+
return null;
|
|
312
|
+
messages.push(message);
|
|
389
313
|
}
|
|
314
|
+
const next = held.next === null || held.next === undefined ? undefined : historyCursor(held.next);
|
|
315
|
+
if (next === null)
|
|
316
|
+
return null;
|
|
317
|
+
return { conversation, messages, ...(next === undefined ? {} : { next: position(next) }) };
|
|
390
318
|
}
|
|
391
|
-
function
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
};
|
|
319
|
+
function historyAsks(input) {
|
|
320
|
+
const asked = record(input).conversations;
|
|
321
|
+
if (!Array.isArray(asked) || asked.length === 0)
|
|
322
|
+
return null;
|
|
323
|
+
const asks = [];
|
|
324
|
+
for (const entry of asked) {
|
|
325
|
+
const conversationId = text(entry, 'conversation');
|
|
326
|
+
if (conversationId === undefined)
|
|
327
|
+
return null;
|
|
328
|
+
const afterValue = text(entry, 'after');
|
|
329
|
+
const after = afterValue === undefined ? undefined : positionCursor(afterValue);
|
|
330
|
+
if (after === null)
|
|
331
|
+
return null;
|
|
332
|
+
asks.push({ conversation_id: conversationId, ...(after === undefined ? {} : { after }) });
|
|
333
|
+
}
|
|
334
|
+
return asks;
|
|
409
335
|
}
|
|
410
336
|
async function historyAction(transport, input) {
|
|
411
|
-
const
|
|
412
|
-
if (
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
337
|
+
const asks = historyAsks(input);
|
|
338
|
+
if (asks === null)
|
|
339
|
+
return malformed();
|
|
340
|
+
const histories = [];
|
|
341
|
+
for (let at = 0; at < asks.length; at += HISTORY_CONVERSATIONS) {
|
|
342
|
+
const answer = await transport.door('/door/conversations/history', {
|
|
343
|
+
conversations: asks.slice(at, at + HISTORY_CONVERSATIONS),
|
|
344
|
+
limit: HISTORY_PAGE,
|
|
345
|
+
});
|
|
346
|
+
const outcome = actionOutcome(answer, 'conversation.history');
|
|
347
|
+
if (outcome.kind !== 'action')
|
|
348
|
+
return outcome;
|
|
349
|
+
const answered = record(outcome.result).histories;
|
|
350
|
+
if (!Array.isArray(answered))
|
|
351
|
+
return { kind: 'transport-uncertainty' };
|
|
352
|
+
for (const entry of answered) {
|
|
353
|
+
const page = historyPage(entry);
|
|
354
|
+
if (page === null)
|
|
355
|
+
return { kind: 'transport-uncertainty' };
|
|
356
|
+
histories.push(page);
|
|
425
357
|
}
|
|
426
|
-
olderThan = parsed;
|
|
427
|
-
}
|
|
428
|
-
const held = await readConversationHistory(transport, conversationId);
|
|
429
|
-
if ('outcome' in held) return held.outcome;
|
|
430
|
-
const messages = [];
|
|
431
|
-
for (const entry of held.messages){
|
|
432
|
-
const mapped = turned(entry);
|
|
433
|
-
if (mapped === null) return {
|
|
434
|
-
kind: 'transport-uncertainty'
|
|
435
|
-
};
|
|
436
|
-
messages.push(mapped);
|
|
437
|
-
}
|
|
438
|
-
if (olderThan === undefined) {
|
|
439
|
-
return historyPage(conversationId, messages, messages.length);
|
|
440
|
-
}
|
|
441
|
-
const at = messages.findIndex((entry)=>text(entry.message, 'accepted_at') === olderThan.accepted_at && text(entry.message, 'message_id') === olderThan.message_id);
|
|
442
|
-
if (at === -1) {
|
|
443
|
-
return {
|
|
444
|
-
kind: 'rejected',
|
|
445
|
-
code: 'unknown-cursor',
|
|
446
|
-
fields: {
|
|
447
|
-
cursor: cursorValue
|
|
448
|
-
}
|
|
449
|
-
};
|
|
450
358
|
}
|
|
451
|
-
|
|
359
|
+
const result = { histories };
|
|
360
|
+
return { kind: 'action', result };
|
|
452
361
|
}
|
|
453
|
-
|
|
454
|
-
//# sourceMappingURL=actions.js.map
|