@agentshouse/mdruntime-adapter 0.1.0-ce3ced044cab5 → 0.1.0-ce3f1a73f440b
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/actions.d.ts +1 -46
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +1 -223
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +60 -213
- package/dist/discovery.d.ts +8 -3
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +29 -22
- package/dist/history.d.ts +12 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +91 -0
- package/dist/house-model.d.ts +954 -1
- package/dist/house-model.d.ts.map +1 -1
- package/dist/house-model.js +521 -486
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/model.d.ts +1 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -17
- package/dist/read.d.ts +1 -44
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +2 -173
- package/dist/refusal.d.ts +0 -3
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +0 -5
- package/dist/room-types.js +1 -1
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +44 -90
- package/dist/stream.d.ts +13 -14
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +160 -423
- package/dist/transport.d.ts +38 -34
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +53 -12
- package/dist/upload.d.ts.map +1 -1
- package/dist/upload.js +2 -2
- package/dist/write.d.ts +2 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +7 -17
- package/package.json +2 -2
- package/dist/gather.d.ts +0 -3
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -35
package/dist/adapter.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { stepped } from '@agentshouse/mdruntime';
|
|
2
|
-
import {
|
|
3
|
-
import { streamedModels, viewModels } from './model.js';
|
|
4
|
-
import { gathered, selections } from './gather.js';
|
|
2
|
+
import { capabilities, discoveredRoom, mapDiscovery, parseAuthorityChange, parseDiscovery, trackedFrom, } from './discovery.js';
|
|
5
3
|
import { createSiteAdapter } from './site.js';
|
|
6
|
-
import { authorityRoot, bootstrapping,
|
|
4
|
+
import { authorityRoot, bootstrapping, parseFileAddress, parseGrant, } from './read.js';
|
|
7
5
|
import { roomStreams } from './room-stream.js';
|
|
8
6
|
import { sha256Hex } from './digest.js';
|
|
9
7
|
import { finishedUpload, houseUpload } from './upload.js';
|
|
10
8
|
import { houseAction } from './actions.js';
|
|
11
|
-
import { classifyDoor,
|
|
12
|
-
import { houseNotifications } from './stream.js';
|
|
13
|
-
import {
|
|
9
|
+
import { classifyDoor, doorRefusal } from './refusal.js';
|
|
10
|
+
import { houseNotifications, } from './stream.js';
|
|
11
|
+
import { houseDoorRoute, } from './transport.js';
|
|
14
12
|
import { batchPaths, deltaBody, deltaBytes, deltaDigest, historyOutcome, houseChanges, houseMove, mutationOutcome, operationHead, rejectedMapping, revisionBody, uploadable, } from './write.js';
|
|
15
13
|
import { HOUSE_NAMEABLE_ROOM_TYPES, HOUSE_ROOM_TYPES } from './room-types.js';
|
|
16
|
-
import { followsVersion, logPosition, presented, reachedVersion, roomVersion
|
|
14
|
+
import { followsVersion, logPosition, presented, reachedVersion, roomVersion } from './version.js';
|
|
17
15
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
18
16
|
const UNCERTAIN_READ = { kind: 'transport-uncertainty' };
|
|
19
17
|
const OCTET_STREAM = 'application/octet-stream';
|
|
@@ -51,18 +49,49 @@ export function createAgentsHouseAdapter(options) {
|
|
|
51
49
|
if ('site' in options)
|
|
52
50
|
return createSiteAdapter(options.site, options.snapshot === true);
|
|
53
51
|
const transport = options.transport;
|
|
54
|
-
const notifications = houseNotifications(transport, 'credential'
|
|
52
|
+
const notifications = houseNotifications(transport, 'credential', {
|
|
53
|
+
opened: async (frame) => (frame === null ? null : opened(frame)),
|
|
54
|
+
changed,
|
|
55
|
+
});
|
|
55
56
|
const tracked = new Map();
|
|
56
|
-
const handed = new Map();
|
|
57
57
|
const rooms = roomStreams('credential');
|
|
58
58
|
const unreused = new Set();
|
|
59
|
-
let heldRevisions;
|
|
60
59
|
let bounds;
|
|
61
60
|
function declared() {
|
|
62
61
|
if (bounds === undefined)
|
|
63
62
|
throw new Error('no Discovery declared the bounds');
|
|
64
63
|
return bounds;
|
|
65
64
|
}
|
|
65
|
+
function opened(frame) {
|
|
66
|
+
const document = parseDiscovery(frame);
|
|
67
|
+
if (document === null)
|
|
68
|
+
return null;
|
|
69
|
+
bounds = document.bounds;
|
|
70
|
+
tracked.clear();
|
|
71
|
+
for (const entry of trackedFrom(document))
|
|
72
|
+
tracked.set(entry.locator, entry);
|
|
73
|
+
notifications.track([...tracked.values()]);
|
|
74
|
+
return {
|
|
75
|
+
...mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document.actions)),
|
|
76
|
+
member: document.member,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function changed(frame) {
|
|
80
|
+
const change = parseAuthorityChange(frame);
|
|
81
|
+
if (change === null)
|
|
82
|
+
return null;
|
|
83
|
+
for (const locator of change.left)
|
|
84
|
+
tracked.delete(locator);
|
|
85
|
+
for (const entry of trackedFrom(change))
|
|
86
|
+
tracked.set(entry.locator, entry);
|
|
87
|
+
notifications.track([...tracked.values()]);
|
|
88
|
+
return {
|
|
89
|
+
kind: 'authority-changed',
|
|
90
|
+
rooms: change.authorities.map((authority) => discoveredRoom(authority)),
|
|
91
|
+
left: change.left,
|
|
92
|
+
member: change.member,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
66
95
|
async function streamedPage(entry, token, held) {
|
|
67
96
|
const part = await rooms.part(entry, token);
|
|
68
97
|
if ('kind' in part)
|
|
@@ -72,11 +101,6 @@ export function createAgentsHouseAdapter(options) {
|
|
|
72
101
|
unreused.add(entry.locator);
|
|
73
102
|
return UNCERTAIN_READ;
|
|
74
103
|
}
|
|
75
|
-
if (part.first && part.ended)
|
|
76
|
-
handed.set(entry.locator, roomVersion(scope));
|
|
77
|
-
else
|
|
78
|
-
handed.delete(entry.locator);
|
|
79
|
-
notifications.reach(entry.authority, scope);
|
|
80
104
|
return {
|
|
81
105
|
...(await stepped(bootstrapping(scope))),
|
|
82
106
|
...(part.models === undefined ? {} : { models: part.models }),
|
|
@@ -89,7 +113,8 @@ export function createAgentsHouseAdapter(options) {
|
|
|
89
113
|
const files = reusing === undefined
|
|
90
114
|
? null
|
|
91
115
|
: await heldFiles(entry.authority, reusing, declared().max_held_files);
|
|
92
|
-
const answered = await transport.streamed(
|
|
116
|
+
const answered = await transport.streamed(houseDoorRoute('bootstrap'), {
|
|
117
|
+
room_ref: entry.authority,
|
|
93
118
|
prefixes: [authorityRoot(entry.handle)],
|
|
94
119
|
...(files === null ? {} : { held: [files] }),
|
|
95
120
|
}, request.signal ?? new AbortController().signal);
|
|
@@ -97,84 +122,12 @@ export function createAgentsHouseAdapter(options) {
|
|
|
97
122
|
return classifyDoor(answered.status, answered.body, entry.locator) ?? UNCERTAIN_READ;
|
|
98
123
|
return rooms.head(entry, answered.room, request.arriving, request.signal);
|
|
99
124
|
}
|
|
100
|
-
async function enumeratedPage(ask, page) {
|
|
101
|
-
const answer = await transport.door(DOOR_ENUMERATE, {
|
|
102
|
-
prefixes: [authorityRoot(ask.entry.handle)],
|
|
103
|
-
positions: [
|
|
104
|
-
{
|
|
105
|
-
...presented(ask.entry.authority, { position: page.after, logEpoch: ask.from.logEpoch }),
|
|
106
|
-
page: { through: page.through, read: page.read },
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
});
|
|
110
|
-
const failure = classifyRead(answer.status, answer.body, ask.entry.locator);
|
|
111
|
-
if (failure !== null)
|
|
112
|
-
return failure;
|
|
113
|
-
const enumeration = parseEnumeration(answer.body, 'credential');
|
|
114
|
-
if (enumeration === null)
|
|
115
|
-
return UNCERTAIN_READ;
|
|
116
|
-
return (viewOf(enumeration, ask.entry) ?? { kind: 'room-not-readable', locator: ask.entry.locator });
|
|
117
|
-
}
|
|
118
|
-
async function enumeratedRoom(enumeration, ask) {
|
|
119
|
-
const first = viewOf(enumeration, ask.entry);
|
|
120
|
-
if (first === undefined)
|
|
121
|
-
return { kind: 'room-not-readable', locator: ask.entry.locator };
|
|
122
|
-
const view = await wholeView(first, (page) => enumeratedPage(ask, page));
|
|
123
|
-
if ('kind' in view)
|
|
124
|
-
return view;
|
|
125
|
-
notifications.reach(ask.entry.authority, view);
|
|
126
|
-
const answer = await refreshFrom(view, ask.fromRoomVersion);
|
|
127
|
-
if (answer.kind !== 'net-advancement')
|
|
128
|
-
return answer;
|
|
129
|
-
handed.set(ask.entry.locator, roomVersion(view));
|
|
130
|
-
const models = await viewModels(view, ask.entry);
|
|
131
|
-
return models === undefined ? answer : { ...answer, models };
|
|
132
|
-
}
|
|
133
|
-
async function streamed(entry, request, from) {
|
|
134
|
-
if (handed.get(entry.locator) !== request.fromRoomVersion)
|
|
135
|
-
return null;
|
|
136
|
-
const asked = notifications.edited(entry, from);
|
|
137
|
-
const kept = asked.length === 0 || heldRevisions === undefined
|
|
138
|
-
? new Map()
|
|
139
|
-
: await heldRevisions(entry.locator, asked);
|
|
140
|
-
const advanced = await stepped(notifications.advance(entry, from, (path, revision) => kept.get(path) === revision));
|
|
141
|
-
if (advanced === null)
|
|
142
|
-
return null;
|
|
143
|
-
handed.set(entry.locator, advanced.page.roomVersion);
|
|
144
|
-
const models = await streamedModels(advanced.schemas, entry, 'credential');
|
|
145
|
-
return models === undefined ? advanced.page : { ...advanced.page, models };
|
|
146
|
-
}
|
|
147
125
|
function held(rooms) {
|
|
148
|
-
|
|
126
|
+
notifications.send(rooms.flatMap((room) => {
|
|
149
127
|
const entry = tracked.get(room.locator);
|
|
150
128
|
const at = logPosition(room.roomVersion);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
handed.set(room.locator, room.roomVersion);
|
|
154
|
-
notifications.reach(entry.authority, at);
|
|
155
|
-
return [presented(entry.authority, at)];
|
|
156
|
-
});
|
|
157
|
-
notifications.send(kept);
|
|
158
|
-
}
|
|
159
|
-
async function adoptedMove(entry, into, outcome) {
|
|
160
|
-
if (outcome.kind === 'accepted' && outcome.destination !== undefined) {
|
|
161
|
-
await adopted(into, { kind: 'accepted', ...outcome.destination });
|
|
162
|
-
}
|
|
163
|
-
return adopted(entry, outcome);
|
|
164
|
-
}
|
|
165
|
-
async function adopted(entry, outcome) {
|
|
166
|
-
if (outcome.kind !== 'accepted')
|
|
167
|
-
return outcome;
|
|
168
|
-
const held = handed.get(entry.locator);
|
|
169
|
-
if (held === undefined)
|
|
170
|
-
return outcome;
|
|
171
|
-
const follows = followsVersion(held, outcome.roomVersion);
|
|
172
|
-
if (follows)
|
|
173
|
-
handed.set(entry.locator, outcome.roomVersion);
|
|
174
|
-
const at = logPosition(outcome.roomVersion);
|
|
175
|
-
if (follows && at !== null)
|
|
176
|
-
notifications.reach(entry.authority, at);
|
|
177
|
-
return outcome;
|
|
129
|
+
return entry === undefined || at === null ? [] : [presented(entry.authority, at)];
|
|
130
|
+
}));
|
|
178
131
|
}
|
|
179
132
|
function authorityFor(locator) {
|
|
180
133
|
return tracked.get(locator);
|
|
@@ -193,60 +146,18 @@ export function createAgentsHouseAdapter(options) {
|
|
|
193
146
|
return result;
|
|
194
147
|
return { ...result, at: { locator, roomVersion: roomVersion({ position, logEpoch }) } };
|
|
195
148
|
}
|
|
196
|
-
function layered(asks) {
|
|
197
|
-
const depths = new Map();
|
|
198
|
-
const layers = [];
|
|
199
|
-
for (const ask of asks) {
|
|
200
|
-
const depth = depths.get(ask.ask.entry.authority) ?? 0;
|
|
201
|
-
depths.set(ask.ask.entry.authority, depth + 1);
|
|
202
|
-
(layers[depth] ??= []).push(ask);
|
|
203
|
-
}
|
|
204
|
-
return layers;
|
|
205
|
-
}
|
|
206
|
-
async function enumerated(asks) {
|
|
207
|
-
const answers = [];
|
|
208
|
-
const parts = layered(asks.map((ask, index) => ({ ask, index }))).flatMap((layer) => selections(layer, declared().max_prefixes));
|
|
209
|
-
for (const part of parts) {
|
|
210
|
-
let open = [...part];
|
|
211
|
-
while (open.length > 0) {
|
|
212
|
-
const answer = await transport.door(DOOR_ENUMERATE, {
|
|
213
|
-
prefixes: open.map(({ ask }) => authorityRoot(ask.entry.handle)),
|
|
214
|
-
positions: open.map(({ ask }) => presented(ask.entry.authority, ask.from)),
|
|
215
|
-
});
|
|
216
|
-
const classified = open.map(({ ask }) => classifyRead(answer.status, answer.body, ask.entry.locator));
|
|
217
|
-
if (classified[0]?.kind === 'beyond-horizon') {
|
|
218
|
-
const named = doorRefusal(answer.body)?.fields.authority;
|
|
219
|
-
const expired = open.filter(({ ask }) => ask.entry.authority === named);
|
|
220
|
-
const answered = expired.length === 0 ? UNCERTAIN_READ : { kind: 'beyond-horizon' };
|
|
221
|
-
const gone = expired.length === 0 ? open : expired;
|
|
222
|
-
for (const ask of gone)
|
|
223
|
-
answers[ask.index] = answered;
|
|
224
|
-
open = open.filter((ask) => !gone.includes(ask));
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
const enumeration = classified[0] === null ? parseEnumeration(answer.body, 'credential') : null;
|
|
228
|
-
for (const [answerIndex, { ask, index }] of open.entries()) {
|
|
229
|
-
const failure = classified[answerIndex];
|
|
230
|
-
if (failure !== null && failure !== undefined) {
|
|
231
|
-
answers[index] = failure;
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
answers[index] =
|
|
235
|
-
enumeration === null ? UNCERTAIN_READ : await enumeratedRoom(enumeration, ask);
|
|
236
|
-
}
|
|
237
|
-
open = [];
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return answers;
|
|
241
|
-
}
|
|
242
|
-
const enumerateTogether = gathered(enumerated);
|
|
243
149
|
async function uploaded(head, changes, delta, bytes, entry, handed, keep) {
|
|
244
150
|
const paths = batchPaths(changes);
|
|
245
151
|
const sha256 = await deltaDigest(delta);
|
|
246
152
|
if (handed !== undefined && handed.sha256 === sha256) {
|
|
247
153
|
return { body: { ...head, paths, upload: handed, runtime: notifications.runtime } };
|
|
248
154
|
}
|
|
249
|
-
const minted = await transport.door(
|
|
155
|
+
const minted = await transport.door(houseDoorRoute('batch-upload'), {
|
|
156
|
+
...head,
|
|
157
|
+
paths,
|
|
158
|
+
bytes,
|
|
159
|
+
sha256,
|
|
160
|
+
});
|
|
250
161
|
if (minted.status !== 200) {
|
|
251
162
|
return {
|
|
252
163
|
outcome: await stepped(mutationOutcome(minted.status, minted.body, entry.locator, entry.handle)),
|
|
@@ -294,11 +205,11 @@ export function createAgentsHouseAdapter(options) {
|
|
|
294
205
|
: { body: inline };
|
|
295
206
|
if ('outcome' in prepared)
|
|
296
207
|
return prepared.outcome;
|
|
297
|
-
const answer = await transport.door(
|
|
208
|
+
const answer = await transport.door(houseDoorRoute('batch'), prepared.body);
|
|
298
209
|
const stagedFiles = await staged(answer, request);
|
|
299
210
|
if (stagedFiles === false)
|
|
300
211
|
return UNCERTAIN;
|
|
301
|
-
const settled = stagedFiles === null ? answer : await transport.door(
|
|
212
|
+
const settled = stagedFiles === null ? answer : await transport.door(houseDoorRoute('batch'), prepared.body);
|
|
302
213
|
if (stagedFiles === true && (await staged(settled, request)) !== null)
|
|
303
214
|
return UNCERTAIN;
|
|
304
215
|
return stepped(mutationOutcome(settled.status, settled.body, entry.locator, entry.handle, into === undefined
|
|
@@ -366,7 +277,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
366
277
|
const entry = authorityFor(request.locator);
|
|
367
278
|
if (entry === undefined)
|
|
368
279
|
return null;
|
|
369
|
-
return () => transport.door(
|
|
280
|
+
return () => transport.door(houseDoorRoute('files/get'), {
|
|
370
281
|
room_ref: entry.authority,
|
|
371
282
|
path: request.path,
|
|
372
283
|
revision: request.revision,
|
|
@@ -378,46 +289,6 @@ export function createAgentsHouseAdapter(options) {
|
|
|
378
289
|
async authorize() {
|
|
379
290
|
return options.authorize();
|
|
380
291
|
},
|
|
381
|
-
async discover(_authorization, scope) {
|
|
382
|
-
const answer = await transport.door(DOOR_DISCOVER, {
|
|
383
|
-
prefixes: [...DISCOVER_PREFIXES],
|
|
384
|
-
...(scope === undefined ? {} : { rooms: scope.authorities }),
|
|
385
|
-
});
|
|
386
|
-
const failed = discoveryFailure(answer.status, answer.body);
|
|
387
|
-
if (failed !== null)
|
|
388
|
-
return failed;
|
|
389
|
-
const document = parseDiscovery(answer.body);
|
|
390
|
-
if (document === null)
|
|
391
|
-
return { kind: 'transport-uncertainty' };
|
|
392
|
-
bounds = document.bounds;
|
|
393
|
-
const entries = trackedFrom(document);
|
|
394
|
-
const covered = scope === undefined
|
|
395
|
-
? null
|
|
396
|
-
: [
|
|
397
|
-
...new Set([
|
|
398
|
-
...[...tracked.values()]
|
|
399
|
-
.filter((entry) => scope.authorities.includes(entry.authority))
|
|
400
|
-
.map((entry) => entry.locator),
|
|
401
|
-
...entries.map((entry) => entry.locator),
|
|
402
|
-
]),
|
|
403
|
-
];
|
|
404
|
-
if (covered === null)
|
|
405
|
-
tracked.clear();
|
|
406
|
-
else
|
|
407
|
-
for (const locator of covered)
|
|
408
|
-
tracked.delete(locator);
|
|
409
|
-
for (const entry of entries)
|
|
410
|
-
tracked.set(entry.locator, entry);
|
|
411
|
-
for (const locator of handed.keys())
|
|
412
|
-
if (!tracked.has(locator))
|
|
413
|
-
handed.delete(locator);
|
|
414
|
-
notifications.track([...tracked.values()]);
|
|
415
|
-
return {
|
|
416
|
-
...mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document.actions, [...tracked.values()])),
|
|
417
|
-
member: document.member,
|
|
418
|
-
...(covered === null ? {} : { covered }),
|
|
419
|
-
};
|
|
420
|
-
},
|
|
421
292
|
async bootstrap(_authorization, request) {
|
|
422
293
|
const entry = authorityFor(request.locator);
|
|
423
294
|
if (entry === undefined)
|
|
@@ -426,20 +297,6 @@ export function createAgentsHouseAdapter(options) {
|
|
|
426
297
|
? openedRoom(entry, request)
|
|
427
298
|
: streamedPage(entry, request.pageToken, request.held);
|
|
428
299
|
},
|
|
429
|
-
async refresh(_authorization, request) {
|
|
430
|
-
const entry = authorityFor(request.locator);
|
|
431
|
-
if (entry === undefined)
|
|
432
|
-
return { kind: 'room-not-readable', locator: request.locator };
|
|
433
|
-
if (request.pageToken !== undefined)
|
|
434
|
-
return { kind: 'transport-uncertainty' };
|
|
435
|
-
const from = logPosition(request.fromRoomVersion);
|
|
436
|
-
if (from === null)
|
|
437
|
-
return { kind: 'beyond-horizon' };
|
|
438
|
-
const answered = await streamed(entry, request, from);
|
|
439
|
-
if (answered !== null)
|
|
440
|
-
return answered;
|
|
441
|
-
return enumerateTogether({ entry, from, fromRoomVersion: request.fromRoomVersion });
|
|
442
|
-
},
|
|
443
300
|
async mutate(_authorization, request, keep) {
|
|
444
301
|
const entry = authorityFor(request.locator);
|
|
445
302
|
if (entry === undefined)
|
|
@@ -455,22 +312,21 @@ export function createAgentsHouseAdapter(options) {
|
|
|
455
312
|
: houseMove(batch, entry.handle, into.handle);
|
|
456
313
|
if (mapped.kind === 'unmapped')
|
|
457
314
|
return rejectedMapping(mapped);
|
|
458
|
-
const head = operationHead(batch);
|
|
315
|
+
const head = operationHead(batch, entry.authority);
|
|
459
316
|
const delta = deltaBody(mapped.changes);
|
|
460
317
|
const bytes = deltaBytes(delta);
|
|
461
318
|
const handed = request.upload;
|
|
462
319
|
const answer = (upload) => submit(request, head, mapped.changes, delta, bytes, entry, upload, keep, into);
|
|
463
|
-
const settle = (outcome) => into === undefined ? adopted(entry, outcome) : adoptedMove(entry, into, outcome);
|
|
464
320
|
const outcome = await answer(handed);
|
|
465
321
|
if (handed === undefined || !lapsedGrant(outcome))
|
|
466
|
-
return
|
|
467
|
-
return
|
|
322
|
+
return outcome;
|
|
323
|
+
return answer(undefined);
|
|
468
324
|
},
|
|
469
325
|
async history(_authorization, request) {
|
|
470
326
|
const entry = authorityFor(request.locator);
|
|
471
327
|
if (entry === undefined)
|
|
472
328
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
473
|
-
const answer = await transport.door(
|
|
329
|
+
const answer = await transport.door(houseDoorRoute('revisions'), revisionBody({
|
|
474
330
|
path: request.path,
|
|
475
331
|
handle: entry.handle,
|
|
476
332
|
...(request.revision === undefined ? {} : { revision: request.revision }),
|
|
@@ -497,7 +353,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
497
353
|
const entry = authorityFor(request.locator);
|
|
498
354
|
if (entry === undefined)
|
|
499
355
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
500
|
-
const declared = await transport.door(
|
|
356
|
+
const declared = await transport.door(houseDoorRoute('files/attach'), {
|
|
501
357
|
room_ref: entry.authority,
|
|
502
358
|
name: request.name,
|
|
503
359
|
bytes: request.byteLength,
|
|
@@ -533,16 +389,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
533
389
|
},
|
|
534
390
|
roomStream: {
|
|
535
391
|
hold: held,
|
|
536
|
-
|
|
537
|
-
observe(notify, receipts, revisions) {
|
|
538
|
-
heldRevisions = revisions;
|
|
539
|
-
return notifications.observe(notify, receipts);
|
|
540
|
-
},
|
|
541
|
-
published(locator, roomVersion) {
|
|
542
|
-
const at = logPosition(roomVersion);
|
|
543
|
-
if (at !== null)
|
|
544
|
-
notifications.published(locator, at);
|
|
545
|
-
},
|
|
392
|
+
observe: notifications.observe,
|
|
546
393
|
},
|
|
547
394
|
conversations: notifications.conversations,
|
|
548
395
|
serviceMode: notifications.serviceMode,
|
package/dist/discovery.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Capability, DiscoveredRoom, Discovery, Member, ProviderLimit, Retention } from '@agentshouse/mdruntime';
|
|
2
2
|
import { type LogPosition } from './version.js';
|
|
3
3
|
export declare const PROVIDER_ACTIONS = "provider-actions";
|
|
4
|
-
export declare const DISCOVER_PREFIXES: readonly string[];
|
|
5
4
|
export type HouseBounds = {
|
|
6
5
|
max_authored_file_bytes: number;
|
|
7
6
|
max_batch_operations: number;
|
|
@@ -40,6 +39,11 @@ export type HouseDiscoveryDocument = {
|
|
|
40
39
|
authorities: readonly HouseAuthority[];
|
|
41
40
|
actions: readonly string[];
|
|
42
41
|
};
|
|
42
|
+
export type HouseAuthorityChange = {
|
|
43
|
+
member: Member;
|
|
44
|
+
authorities: readonly HouseAuthority[];
|
|
45
|
+
left: readonly string[];
|
|
46
|
+
};
|
|
43
47
|
export type TrackedAuthority = LogPosition & {
|
|
44
48
|
locator: string;
|
|
45
49
|
authority: string;
|
|
@@ -57,12 +61,13 @@ export type HouseSiteDiscovery = {
|
|
|
57
61
|
authorities: readonly HouseSiteAuthority[];
|
|
58
62
|
};
|
|
59
63
|
export declare function parseDiscovery(body: unknown): HouseDiscoveryDocument | null;
|
|
64
|
+
export declare function parseAuthorityChange(body: unknown): HouseAuthorityChange | null;
|
|
60
65
|
export declare function parseSiteDiscovery(body: unknown): HouseSiteDiscovery | null;
|
|
61
66
|
export declare function siteTracked(document: HouseSiteDiscovery): TrackedAuthority[];
|
|
62
|
-
export declare function trackedFrom(document: HouseDiscoveryDocument): TrackedAuthority[];
|
|
67
|
+
export declare function trackedFrom(document: Pick<HouseDiscoveryDocument, 'authorities'>): TrackedAuthority[];
|
|
63
68
|
export declare function providerLimits(bounds: HouseBounds): readonly ProviderLimit[];
|
|
64
69
|
export declare function declaredRetention(bounds: HouseBounds): Retention;
|
|
65
|
-
export declare function capabilities(actions: HouseDiscoveryDocument['actions']
|
|
70
|
+
export declare function capabilities(actions: HouseDiscoveryDocument['actions']): readonly Capability[];
|
|
66
71
|
export declare function siteCapabilities(): readonly Capability[];
|
|
67
72
|
export declare function discoveredRoom(authority: HouseAuthority): DiscoveredRoom;
|
|
68
73
|
export declare function mapDiscovery(document: Pick<HouseDiscoveryDocument, 'bounds'>, rooms: readonly DiscoveredRoom[], declared: readonly Capability[]): Discovery;
|
package/dist/discovery.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,SAAS,EACT,MAAM,EACN,aAAa,EACb,SAAS,EACV,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
|
package/dist/discovery.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { declaredActions
|
|
1
|
+
import { declaredActions } from './actions.js';
|
|
2
|
+
import { SITE_SUBMISSION } from './transport.js';
|
|
2
3
|
import { readPosition, roomVersion } from './version.js';
|
|
3
4
|
export const PROVIDER_ACTIONS = 'provider-actions';
|
|
4
|
-
export const DISCOVER_PREFIXES = ['/'];
|
|
5
|
-
const PRIVATE_HANDLE = 'private';
|
|
6
5
|
const BOUND_KEYS = [
|
|
7
6
|
'max_authored_file_bytes',
|
|
8
7
|
'max_batch_operations',
|
|
@@ -111,6 +110,18 @@ function parseAuthority(value) {
|
|
|
111
110
|
...at,
|
|
112
111
|
};
|
|
113
112
|
}
|
|
113
|
+
function parseAuthorities(value) {
|
|
114
|
+
if (!Array.isArray(value))
|
|
115
|
+
return null;
|
|
116
|
+
const authorities = [];
|
|
117
|
+
for (const entry of value) {
|
|
118
|
+
const authority = parseAuthority(entry);
|
|
119
|
+
if (authority === null)
|
|
120
|
+
return null;
|
|
121
|
+
authorities.push(authority);
|
|
122
|
+
}
|
|
123
|
+
return authorities;
|
|
124
|
+
}
|
|
114
125
|
export function parseDiscovery(body) {
|
|
115
126
|
if (typeof body !== 'object' || body === null)
|
|
116
127
|
return null;
|
|
@@ -126,16 +137,19 @@ export function parseDiscovery(body) {
|
|
|
126
137
|
new Set(actions).size !== actions.length ||
|
|
127
138
|
actions.some((name) => name.length === 0))
|
|
128
139
|
return null;
|
|
129
|
-
|
|
140
|
+
const authorities = parseAuthorities(held.authorities);
|
|
141
|
+
return authorities === null ? null : { member, bounds, authorities, actions };
|
|
142
|
+
}
|
|
143
|
+
export function parseAuthorityChange(body) {
|
|
144
|
+
if (typeof body !== 'object' || body === null)
|
|
130
145
|
return null;
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
return { member, bounds, authorities, actions };
|
|
146
|
+
const held = body;
|
|
147
|
+
const member = parseMember(held.member);
|
|
148
|
+
const authorities = parseAuthorities(held.authorities);
|
|
149
|
+
const left = stringList(held.left);
|
|
150
|
+
if (member === null || authorities === null || left === null)
|
|
151
|
+
return null;
|
|
152
|
+
return { member, authorities, left };
|
|
139
153
|
}
|
|
140
154
|
function parseSiteAuthority(value) {
|
|
141
155
|
if (typeof value !== 'object' || value === null)
|
|
@@ -220,21 +234,14 @@ export function declaredRetention(bounds) {
|
|
|
220
234
|
refreshHorizon: bounds.change_retention_seconds,
|
|
221
235
|
};
|
|
222
236
|
}
|
|
223
|
-
export function capabilities(actions
|
|
224
|
-
|
|
225
|
-
return [
|
|
226
|
-
{
|
|
227
|
-
name: PROVIDER_ACTIONS,
|
|
228
|
-
actions: declaredActions(actions),
|
|
229
|
-
...(own === undefined ? {} : { conversationAgents: houseConversationAgents(own.authority) }),
|
|
230
|
-
},
|
|
231
|
-
];
|
|
237
|
+
export function capabilities(actions) {
|
|
238
|
+
return [{ name: PROVIDER_ACTIONS, actions: declaredActions(actions) }];
|
|
232
239
|
}
|
|
233
240
|
export function siteCapabilities() {
|
|
234
241
|
return [
|
|
235
242
|
{
|
|
236
243
|
name: PROVIDER_ACTIONS,
|
|
237
|
-
actions: [{ name:
|
|
244
|
+
actions: [{ name: SITE_SUBMISSION, inputShape: {}, resultKind: 'house' }],
|
|
238
245
|
},
|
|
239
246
|
];
|
|
240
247
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AcceptedMessage, ActionResult, ConversationHistoryRequest } from '@agentshouse/mdruntime';
|
|
2
|
+
import { type HouseDoor } from './transport.js';
|
|
3
|
+
export declare const HISTORY_PAGE = 100;
|
|
4
|
+
type HistoryCursor = {
|
|
5
|
+
accepted_at: string;
|
|
6
|
+
message_id: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function cursorPosition(cursor: HistoryCursor): string;
|
|
9
|
+
export declare function acceptedMessage(entry: unknown): AcceptedMessage | null;
|
|
10
|
+
export declare function houseHistory(transport: HouseDoor, request: ConversationHistoryRequest): Promise<ActionResult>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EAGZ,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhE,eAAO,MAAM,YAAY,MAAM,CAAC;AAIhC,KAAK,aAAa,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAkBjE,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAE5D;AAUD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAUtE;AA8BD,wBAAsB,YAAY,CAChC,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,YAAY,CAAC,CAmBvB"}
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { actionOutcome } from './actions.js';
|
|
2
|
+
import { houseDoorRoute } from './transport.js';
|
|
3
|
+
export const HISTORY_PAGE = 100;
|
|
4
|
+
const HISTORY = 'conversations/history';
|
|
5
|
+
function record(value) {
|
|
6
|
+
return typeof value === 'object' && value !== null ? value : {};
|
|
7
|
+
}
|
|
8
|
+
function text(value, name) {
|
|
9
|
+
const held = record(value)[name];
|
|
10
|
+
return typeof held === 'string' ? held : undefined;
|
|
11
|
+
}
|
|
12
|
+
function historyCursor(value) {
|
|
13
|
+
const acceptedAt = text(value, 'accepted_at');
|
|
14
|
+
const messageId = text(value, 'message_id');
|
|
15
|
+
if (acceptedAt === undefined || messageId === undefined)
|
|
16
|
+
return null;
|
|
17
|
+
return { accepted_at: acceptedAt, message_id: messageId };
|
|
18
|
+
}
|
|
19
|
+
export function cursorPosition(cursor) {
|
|
20
|
+
return JSON.stringify({ accepted_at: cursor.accepted_at, message_id: cursor.message_id });
|
|
21
|
+
}
|
|
22
|
+
function positionCursor(value) {
|
|
23
|
+
try {
|
|
24
|
+
return historyCursor(JSON.parse(value));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function acceptedMessage(entry) {
|
|
31
|
+
const cursor = historyCursor(entry);
|
|
32
|
+
if (cursor === null)
|
|
33
|
+
return null;
|
|
34
|
+
return {
|
|
35
|
+
identity: cursor.message_id,
|
|
36
|
+
turn: text(entry, 'turn_id') ?? cursor.message_id,
|
|
37
|
+
position: cursorPosition(cursor),
|
|
38
|
+
text: text(entry, 'text') ?? '',
|
|
39
|
+
message: structuredClone(record(entry)),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function historyPage(entry) {
|
|
43
|
+
const held = record(entry);
|
|
44
|
+
const conversation = text(held, 'conversation_id');
|
|
45
|
+
if (conversation === undefined || !Array.isArray(held.messages))
|
|
46
|
+
return null;
|
|
47
|
+
const messages = [];
|
|
48
|
+
for (const one of held.messages) {
|
|
49
|
+
const message = acceptedMessage(one);
|
|
50
|
+
if (message === null)
|
|
51
|
+
return null;
|
|
52
|
+
messages.push(message);
|
|
53
|
+
}
|
|
54
|
+
const next = held.next === null || held.next === undefined ? undefined : historyCursor(held.next);
|
|
55
|
+
if (next === null)
|
|
56
|
+
return null;
|
|
57
|
+
return { conversation, messages, ...(next === undefined ? {} : { next: cursorPosition(next) }) };
|
|
58
|
+
}
|
|
59
|
+
function historyAsks(request) {
|
|
60
|
+
const asks = [];
|
|
61
|
+
for (const { conversation, after } of request.conversations) {
|
|
62
|
+
const cursor = after === undefined ? undefined : positionCursor(after);
|
|
63
|
+
if (cursor === null)
|
|
64
|
+
return null;
|
|
65
|
+
asks.push({
|
|
66
|
+
conversation_id: conversation,
|
|
67
|
+
...(cursor === undefined ? {} : { after: cursor }),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return asks;
|
|
71
|
+
}
|
|
72
|
+
export async function houseHistory(transport, request) {
|
|
73
|
+
const asks = historyAsks(request);
|
|
74
|
+
if (asks === null)
|
|
75
|
+
return { kind: 'rejected', code: 'invalid_request', fields: {}, retryable: false };
|
|
76
|
+
const outcome = actionOutcome(await transport.door(houseDoorRoute(HISTORY), { conversations: asks, limit: HISTORY_PAGE }), HISTORY);
|
|
77
|
+
if (outcome.kind !== 'action')
|
|
78
|
+
return outcome;
|
|
79
|
+
const answered = record(outcome.result).histories;
|
|
80
|
+
if (!Array.isArray(answered))
|
|
81
|
+
return { kind: 'transport-uncertainty' };
|
|
82
|
+
const histories = [];
|
|
83
|
+
for (const entry of answered) {
|
|
84
|
+
const page = historyPage(entry);
|
|
85
|
+
if (page === null)
|
|
86
|
+
return { kind: 'transport-uncertainty' };
|
|
87
|
+
histories.push(page);
|
|
88
|
+
}
|
|
89
|
+
const result = { histories };
|
|
90
|
+
return { kind: 'action', result };
|
|
91
|
+
}
|