@agentshouse/mdruntime-adapter 0.1.0-ca0d16f904a93 → 0.1.0-ca231c2cbedb4
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/README.md +2 -2
- package/dist/actions.d.ts +4 -22
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +23 -134
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +292 -171
- package/dist/app-reference.d.ts +2 -0
- package/dist/app-reference.d.ts.map +1 -0
- package/dist/app-reference.js +2 -0
- package/dist/crockford.d.ts +4 -0
- package/dist/crockford.d.ts.map +1 -0
- package/dist/crockford.js +3 -0
- package/dist/discovery.d.ts +6 -10
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +37 -32
- package/dist/gather.d.ts +1 -1
- package/dist/gather.d.ts.map +1 -1
- package/dist/gather.js +4 -14
- package/dist/house-model.d.ts +2 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +484 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/model.d.ts +5 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +11 -13
- package/dist/part.d.ts +15 -0
- package/dist/part.d.ts.map +1 -0
- package/dist/part.js +82 -0
- package/dist/read.d.ts +58 -24
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +270 -144
- package/dist/room-types.d.ts +7 -0
- package/dist/room-types.d.ts.map +1 -0
- package/dist/room-types.js +124 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +101 -107
- package/dist/stream.d.ts +5 -5
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +66 -39
- package/dist/transport.d.ts +33 -16
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +2 -1
- package/dist/upload.d.ts +12 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +63 -0
- package/dist/write.d.ts +12 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +93 -55
- package/package.json +8 -4
- package/AGENTS.md +0 -300
- package/dist/handed.d.ts +0 -15
- package/dist/handed.d.ts.map +0 -1
- package/dist/handed.js +0 -38
- package/dist/referrer.d.ts +0 -7
- package/dist/referrer.d.ts.map +0 -1
- package/dist/referrer.js +0 -35
package/dist/site.js
CHANGED
|
@@ -1,34 +1,38 @@
|
|
|
1
|
+
import { stepped } from '@agentshouse/mdruntime';
|
|
1
2
|
import { actionOutcome, SITE_SUBMIT } from './actions.js';
|
|
2
3
|
import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteTracked, } from './discovery.js';
|
|
3
|
-
import { partModels, streamedModels, viewModels } from './model.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { manifestedModels, partModels, streamedModels, viewModels } from './model.js';
|
|
5
|
+
import { bootstrapping, emptyScope, housePart, manifested, parseEnumeration, parseSiteParted, partInventory, refreshFrom, viewOf, wholeView, } from './read.js';
|
|
6
|
+
import { PART_ATTEMPTS, partArrival, partFrame, unverifiedPart } from './part.js';
|
|
6
7
|
import { classifyDoor, classifyRead, discoveryFailure } from './refusal.js';
|
|
8
|
+
import { HOUSE_NAMEABLE_ROOM_TYPES, HOUSE_ROOM_TYPES } from './room-types.js';
|
|
7
9
|
import { houseNotifications } from './stream.js';
|
|
8
|
-
import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT,
|
|
9
|
-
import { houseReferrer } from './referrer.js';
|
|
10
|
+
import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT, SITE_FILES, } from './transport.js';
|
|
10
11
|
import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
|
|
11
12
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
13
|
+
function unfound() {
|
|
14
|
+
return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
|
|
15
|
+
}
|
|
12
16
|
function siteRoom(tracked) {
|
|
13
17
|
return {
|
|
14
18
|
name: tracked.handle,
|
|
15
19
|
locator: tracked.locator,
|
|
16
20
|
handle: tracked.handle,
|
|
17
21
|
roomVersion: roomVersion(tracked),
|
|
18
|
-
operations: {
|
|
19
|
-
replica: { selection: tracked.locator, admission: 'admitted' },
|
|
22
|
+
operations: { write: [], delete: [] },
|
|
23
|
+
replica: { selection: tracked.locator, admission: 'admitted', offline: 'open' },
|
|
20
24
|
providerOwnedPaths: [],
|
|
21
25
|
};
|
|
22
26
|
}
|
|
23
|
-
function settled(refused) {
|
|
24
|
-
return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;
|
|
25
|
-
}
|
|
26
27
|
export function createSiteAdapter(transport, snapshot = false) {
|
|
27
28
|
const notifications = houseNotifications(transport, 'site');
|
|
28
29
|
const tracked = new Map();
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
const expired = new Map();
|
|
31
|
+
function fileRoute(request) {
|
|
32
|
+
const entry = tracked.get(request.locator);
|
|
33
|
+
if (entry === undefined)
|
|
34
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
35
|
+
return `${SITE_FILES}${entry.authority}/${encodeURIComponent(request.revision)}/${encodeURIComponent(request.path)}`;
|
|
32
36
|
}
|
|
33
37
|
async function enumerated(entry, from, page) {
|
|
34
38
|
const answer = await transport.door(SITE_DOOR_ENUMERATE, {
|
|
@@ -53,73 +57,43 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
53
57
|
const first = await enumerated(entry, from);
|
|
54
58
|
return 'kind' in first ? first : wholeView(first, (page) => enumerated(entry, from, page));
|
|
55
59
|
}
|
|
56
|
-
async function
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
...(offset === null ? [] : [`offset=${offset}`]),
|
|
60
|
-
];
|
|
61
|
-
const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}${query.length === 0 ? '' : `?${query.join('&')}`}`);
|
|
60
|
+
async function partedRoom(entry) {
|
|
61
|
+
const cut = expired.get(entry.locator);
|
|
62
|
+
const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}${cut === undefined ? '' : `?expired=${cut}`}`);
|
|
62
63
|
const classified = classifyDoor(answer.status, answer.body, entry.locator);
|
|
63
64
|
if (classified !== null)
|
|
64
|
-
return
|
|
65
|
-
const
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
async function assembled(entry, scope, path, offset) {
|
|
69
|
-
const opened = scope.contents.at(-1);
|
|
70
|
-
if (opened === undefined || opened.path !== path || opened.content.length !== offset) {
|
|
71
|
-
return UNCERTAIN;
|
|
72
|
-
}
|
|
73
|
-
let text = opened.content;
|
|
74
|
-
for (;;) {
|
|
75
|
-
const part = await bootstrapPart(entry, path, text.length);
|
|
76
|
-
if ('failure' in part)
|
|
77
|
-
return part.failure;
|
|
78
|
-
const [piece] = part.scope.contents;
|
|
79
|
-
if (piece === undefined ||
|
|
80
|
-
part.scope.contents.length !== 1 ||
|
|
81
|
-
piece.path !== path ||
|
|
82
|
-
piece.content.length === 0) {
|
|
83
|
-
return UNCERTAIN;
|
|
84
|
-
}
|
|
85
|
-
text += piece.content;
|
|
86
|
-
const more = siteBootstrapOffset(part.body);
|
|
87
|
-
if (more === null)
|
|
88
|
-
break;
|
|
89
|
-
if (more !== text.length)
|
|
90
|
-
return UNCERTAIN;
|
|
91
|
-
}
|
|
92
|
-
const file = scope.files.find((held) => held.path === path);
|
|
93
|
-
if (file === undefined || (await sha256Hex(text)) !== file.version)
|
|
94
|
-
return UNCERTAIN;
|
|
95
|
-
return { ...scope, contents: [...scope.contents.slice(0, -1), { path, content: text }] };
|
|
65
|
+
return classified;
|
|
66
|
+
const room = parseSiteParted(answer.body);
|
|
67
|
+
return room === null || room.anchor !== entry.authority ? UNCERTAIN : room;
|
|
96
68
|
}
|
|
97
|
-
async function
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (offset !== null) {
|
|
104
|
-
if (next === null)
|
|
105
|
-
return { failure: UNCERTAIN };
|
|
106
|
-
const scope = await assembled(entry, part.scope, next, offset);
|
|
107
|
-
return 'kind' in scope ? { failure: scope } : { scope, next };
|
|
69
|
+
async function fetchedPart(entry, room, listed, received, arriving) {
|
|
70
|
+
if (received !== undefined) {
|
|
71
|
+
const kept = new Uint8Array(received);
|
|
72
|
+
const held = await housePart(room, kept, listed, 'site');
|
|
73
|
+
if (held !== null)
|
|
74
|
+
return 'kind' in held ? held : { scope: held, frame: kept };
|
|
108
75
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
76
|
+
for (let attempt = 0; attempt < PART_ATTEMPTS; attempt += 1) {
|
|
77
|
+
const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}?part=${encodeURIComponent(listed.part)}`, partArrival(listed, arriving));
|
|
78
|
+
const failure = classifyRead(answer.status, answer.body, entry.locator);
|
|
79
|
+
if (failure?.kind === 'beyond-horizon')
|
|
80
|
+
expired.set(entry.locator, room.position);
|
|
81
|
+
if (failure !== null)
|
|
82
|
+
return failure;
|
|
83
|
+
const frame = partFrame(answer.body);
|
|
84
|
+
if (frame === null)
|
|
85
|
+
continue;
|
|
86
|
+
const scope = await housePart(room, frame, listed, 'site');
|
|
87
|
+
if (scope !== null)
|
|
88
|
+
return 'kind' in scope ? scope : { scope, frame };
|
|
112
89
|
}
|
|
113
|
-
|
|
114
|
-
if ('kind' in view)
|
|
115
|
-
return { failure: settled(view) };
|
|
116
|
-
return { scope: advancedScope(scope, view), next: null };
|
|
90
|
+
return unverifiedPart(entry.locator);
|
|
117
91
|
}
|
|
118
92
|
async function refreshed(entry, fromRoomVersion) {
|
|
119
93
|
const from = logPosition(fromRoomVersion);
|
|
120
94
|
if (from === null)
|
|
121
95
|
return { kind: 'beyond-horizon' };
|
|
122
|
-
const streamed = notifications.advance(entry, from);
|
|
96
|
+
const streamed = await stepped(notifications.advance(entry, from));
|
|
123
97
|
if (streamed !== null) {
|
|
124
98
|
const models = await streamedModels(streamed.schemas, entry, 'site');
|
|
125
99
|
return models === undefined ? streamed.page : { ...streamed.page, models };
|
|
@@ -128,7 +102,7 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
128
102
|
if ('kind' in view)
|
|
129
103
|
return view;
|
|
130
104
|
notifications.reach(entry.authority, view);
|
|
131
|
-
const answer = refreshFrom(view, fromRoomVersion);
|
|
105
|
+
const answer = await refreshFrom(view, fromRoomVersion);
|
|
132
106
|
if (answer.kind !== 'net-advancement')
|
|
133
107
|
return answer;
|
|
134
108
|
const models = await viewModels(view, entry);
|
|
@@ -137,6 +111,8 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
137
111
|
return {
|
|
138
112
|
localSaves: true,
|
|
139
113
|
exhaustiveDiscovery: true,
|
|
114
|
+
roomTypes: HOUSE_ROOM_TYPES,
|
|
115
|
+
nameableRoomTypes: HOUSE_NAMEABLE_ROOM_TYPES,
|
|
140
116
|
async authorize() {
|
|
141
117
|
return {};
|
|
142
118
|
},
|
|
@@ -159,23 +135,43 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
159
135
|
const entry = tracked.get(request.locator);
|
|
160
136
|
if (entry === undefined)
|
|
161
137
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
138
|
+
let continued;
|
|
139
|
+
let inventory;
|
|
140
|
+
if (request.pageToken === undefined) {
|
|
141
|
+
const room = await partedRoom(entry);
|
|
142
|
+
if ('kind' in room)
|
|
143
|
+
return room;
|
|
144
|
+
const { models, seen } = await manifestedModels(room, entry);
|
|
145
|
+
continued = { room, next: 0, seen };
|
|
146
|
+
inventory = partInventory(room);
|
|
147
|
+
if (inventory.parts > 0) {
|
|
148
|
+
return manifested(room, inventory, JSON.stringify(continued), models);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else
|
|
152
|
+
continued = JSON.parse(request.pageToken);
|
|
153
|
+
const listed = continued.room.parts[continued.next];
|
|
154
|
+
const sent = listed === undefined
|
|
155
|
+
? { scope: emptyScope(continued.room), frame: null }
|
|
156
|
+
: await fetchedPart(entry, continued.room, listed, request.received, request.arriving);
|
|
157
|
+
if ('kind' in sent)
|
|
158
|
+
return sent;
|
|
159
|
+
const { scope } = sent;
|
|
160
|
+
notifications.reach(entry.authority, scope);
|
|
161
|
+
const next = continued.next + 1;
|
|
162
|
+
const more = next < continued.room.parts.length;
|
|
169
163
|
const seen = [
|
|
170
|
-
...
|
|
171
|
-
...
|
|
164
|
+
...continued.seen,
|
|
165
|
+
...(scope.files.some((file) => file.path === entry.schema) ? [entry.schema] : []),
|
|
172
166
|
];
|
|
173
|
-
const models = await partModels(
|
|
174
|
-
const
|
|
167
|
+
const models = await partModels(scope, entry, new Set(seen), !more);
|
|
168
|
+
const { folders: _folders, ...page } = await stepped(bootstrapping(scope));
|
|
175
169
|
return {
|
|
176
|
-
...
|
|
170
|
+
...page,
|
|
177
171
|
...(models === undefined ? {} : { models }),
|
|
178
|
-
...(
|
|
172
|
+
...(more ? { pageToken: JSON.stringify({ ...continued, next, seen }) } : {}),
|
|
173
|
+
...(inventory === undefined ? {} : { inventory }),
|
|
174
|
+
...(sent.frame === null ? {} : { received: sent.frame }),
|
|
179
175
|
};
|
|
180
176
|
},
|
|
181
177
|
async refresh(_authorization, request) {
|
|
@@ -194,34 +190,32 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
194
190
|
async mutate() {
|
|
195
191
|
return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {}, retryable: false };
|
|
196
192
|
},
|
|
193
|
+
async attach() {
|
|
194
|
+
return { kind: 'rejected', code: 'write-grant', fields: {}, retryable: false };
|
|
195
|
+
},
|
|
197
196
|
async history() {
|
|
198
197
|
return { kind: 'no-history' };
|
|
199
198
|
},
|
|
200
199
|
async binary(_authorization, request) {
|
|
201
|
-
const
|
|
202
|
-
if (
|
|
203
|
-
return
|
|
204
|
-
|
|
205
|
-
if (
|
|
206
|
-
return
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const read = await transport.download(`${SITE_FILES}${room_ref}/${encodeURIComponent(request.fileRef)}/${path === undefined
|
|
210
|
-
? `${SITE_FILE_RECORD}/${encodeURIComponent(record)}`
|
|
211
|
-
: encodeURIComponent(path)}`);
|
|
212
|
-
if (read.status === 404) {
|
|
213
|
-
return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
|
|
214
|
-
}
|
|
215
|
-
return read.status === 200 && read.blob !== null
|
|
216
|
-
? { kind: 'binary', blob: read.blob }
|
|
200
|
+
const route = fileRoute(request);
|
|
201
|
+
if (typeof route !== 'string')
|
|
202
|
+
return route;
|
|
203
|
+
const read = await transport.download(route);
|
|
204
|
+
if (read.status === 404)
|
|
205
|
+
return unfound();
|
|
206
|
+
return read.status === 200 && read.body !== null
|
|
207
|
+
? { kind: 'binary', body: read.body, mediaType: read.mediaType }
|
|
217
208
|
: UNCERTAIN;
|
|
218
209
|
},
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
if (
|
|
222
|
-
return
|
|
223
|
-
|
|
224
|
-
|
|
210
|
+
async link(_authorization, request) {
|
|
211
|
+
const route = fileRoute(request);
|
|
212
|
+
if (typeof route !== 'string')
|
|
213
|
+
return route;
|
|
214
|
+
return {
|
|
215
|
+
kind: 'link',
|
|
216
|
+
url: route,
|
|
217
|
+
name: request.path.slice(request.path.lastIndexOf('/') + 1),
|
|
218
|
+
};
|
|
225
219
|
},
|
|
226
220
|
reached(locator, version, target) {
|
|
227
221
|
return reachedVersion(version, target, tracked.get(locator)?.logEpoch);
|
|
@@ -253,7 +247,7 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
253
247
|
return [];
|
|
254
248
|
notifications.reach(entry.authority, at);
|
|
255
249
|
return [presented(entry.authority, at)];
|
|
256
|
-
})
|
|
250
|
+
}));
|
|
257
251
|
},
|
|
258
252
|
reopen: notifications.reopen,
|
|
259
253
|
observe: notifications.observe,
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ConversationStream, type RefreshPage, type RoomStreamEvent, type ServiceModeSignal, type StreamReceipts } from '@agentshouse/mdruntime';
|
|
2
2
|
import type { TrackedAuthority } from './discovery.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { HouseDoor, HouseHeldRoom, HouseMode, HouseStreamEntry } from './transport.js';
|
|
4
4
|
import { type LogPosition } from './version.js';
|
|
5
5
|
export type HeldRevision = (path: string, revision: string) => boolean;
|
|
6
6
|
export type StreamedAdvancement = {
|
|
7
7
|
page: RefreshPage;
|
|
8
|
-
entries: readonly HouseStreamEntry[];
|
|
9
8
|
schemas: ReadonlyMap<string, HouseStreamEntry>;
|
|
10
9
|
};
|
|
11
10
|
export type HouseNotifications = {
|
|
12
11
|
runtime: string;
|
|
13
12
|
observe(notify: (event: RoomStreamEvent) => void, receipts: StreamReceipts): () => void;
|
|
14
|
-
send(rooms: readonly HouseHeldRoom[]
|
|
13
|
+
send(rooms: readonly HouseHeldRoom[]): void;
|
|
15
14
|
published(locator: string, at: LogPosition): void;
|
|
16
15
|
reopen(): void;
|
|
17
16
|
track(authorities: readonly TrackedAuthority[]): void;
|
|
18
17
|
reach(authority: string, at: LogPosition): void;
|
|
19
|
-
|
|
18
|
+
edited(tracked: TrackedAuthority, from: LogPosition): readonly string[];
|
|
19
|
+
advance(tracked: TrackedAuthority, from: LogPosition, holds?: HeldRevision): Generator<number, StreamedAdvancement | null, void>;
|
|
20
20
|
conversations: ConversationStream;
|
|
21
21
|
serviceMode: ServiceModeSignal;
|
|
22
22
|
};
|
package/dist/stream.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,kBAAkB,EAEvB,KAAK,WAAW,EAChB,KAAK,eAAe,EAEpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAUvD,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EAEb,SAAS,EAET,gBAAgB,EAEjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AA0C7D,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;AAEvE,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI,CAAC;IACxF,IAAI,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAAC;IAC5C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAClD,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,MAAM,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,SAAS,MAAM,EAAE,CAAC;IACxE,OAAO,CACL,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,KAAK,CAAC,EAAE,YAAY,GACnB,SAAS,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC;IACvD,aAAa,EAAE,kBAAkB,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAmFF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CA8jB5F"}
|
package/dist/stream.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { ROW_WEIGHT, } from '@agentshouse/mdruntime';
|
|
1
2
|
import { acceptedMessage } from './actions.js';
|
|
2
3
|
import { sha256Hex } from './digest.js';
|
|
3
|
-
import { binaryFileOf, headChange } from './read.js';
|
|
4
|
+
import { answered, answering, binaryFileOf, folded, forgotten, headChange, revised, } from './read.js';
|
|
4
5
|
import { roomVersion } from './version.js';
|
|
5
6
|
const HELD_FRAMES_MAX = 256;
|
|
6
7
|
function turnOperation(frame) {
|
|
@@ -15,6 +16,7 @@ function listedConversation(listed) {
|
|
|
15
16
|
created: listed.created_at,
|
|
16
17
|
finished: listed.finished_at,
|
|
17
18
|
outcome: listed.outcome,
|
|
19
|
+
waiting: listed.waiting,
|
|
18
20
|
};
|
|
19
21
|
}
|
|
20
22
|
function position(value) {
|
|
@@ -111,7 +113,10 @@ export function houseNotifications(transport, mode) {
|
|
|
111
113
|
event.kind === 'questions' ||
|
|
112
114
|
event.kind === 'process' ||
|
|
113
115
|
event.kind === 'commands' ||
|
|
114
|
-
event.kind === 'options'
|
|
116
|
+
event.kind === 'options' ||
|
|
117
|
+
event.kind === 'starting' ||
|
|
118
|
+
event.kind === 'link' ||
|
|
119
|
+
event.kind === 'deliveries') {
|
|
115
120
|
live.add(event.conversation);
|
|
116
121
|
}
|
|
117
122
|
for (const observer of conversationObservers)
|
|
@@ -157,6 +162,18 @@ export function houseNotifications(transport, mode) {
|
|
|
157
162
|
emitConversation({ kind: 'options', conversation, options: structuredClone(frame.options) });
|
|
158
163
|
return;
|
|
159
164
|
}
|
|
165
|
+
if (frame.type === 'starting') {
|
|
166
|
+
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (frame.type === 'link') {
|
|
170
|
+
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (frame.type === 'deliveries') {
|
|
174
|
+
emitConversation({ kind: 'deliveries', conversation, unknown: [...frame.unknown] });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
160
177
|
if (frame.type === 'interactions') {
|
|
161
178
|
emitConversation({
|
|
162
179
|
kind: 'questions',
|
|
@@ -352,6 +369,10 @@ export function houseNotifications(transport, mode) {
|
|
|
352
369
|
});
|
|
353
370
|
return;
|
|
354
371
|
}
|
|
372
|
+
if (frame.type === 'authority_changed') {
|
|
373
|
+
emit({ kind: 'authority-changed', scope: { authorities: frame.rooms } });
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
355
376
|
if (frame.type === 'conversations') {
|
|
356
377
|
emitConversation({ kind: 'list', entries: frame.conversations.map(listedConversation) });
|
|
357
378
|
return;
|
|
@@ -368,6 +389,9 @@ export function houseNotifications(transport, mode) {
|
|
|
368
389
|
frame.type === 'process' ||
|
|
369
390
|
frame.type === 'commands' ||
|
|
370
391
|
frame.type === 'options' ||
|
|
392
|
+
frame.type === 'starting' ||
|
|
393
|
+
frame.type === 'link' ||
|
|
394
|
+
frame.type === 'deliveries' ||
|
|
371
395
|
frame.type === 'interactions' ||
|
|
372
396
|
frame.type === 'message') {
|
|
373
397
|
converse(frame);
|
|
@@ -421,10 +445,10 @@ export function houseNotifications(transport, mode) {
|
|
|
421
445
|
});
|
|
422
446
|
});
|
|
423
447
|
stream.opened(reopened);
|
|
424
|
-
stream.closed((revoked) => {
|
|
448
|
+
stream.closed(({ revoked, lost }) => {
|
|
425
449
|
opening = null;
|
|
426
450
|
acknowledging = null;
|
|
427
|
-
emit({ kind: 'closed', revoked });
|
|
451
|
+
emit({ kind: 'closed', revoked, lost });
|
|
428
452
|
});
|
|
429
453
|
return {
|
|
430
454
|
runtime,
|
|
@@ -463,7 +487,7 @@ export function houseNotifications(transport, mode) {
|
|
|
463
487
|
observers.delete(notify);
|
|
464
488
|
};
|
|
465
489
|
},
|
|
466
|
-
send(rooms
|
|
490
|
+
send(rooms) {
|
|
467
491
|
for (const room of rooms) {
|
|
468
492
|
const line = lines.get(room.authority);
|
|
469
493
|
const held = position(room.position);
|
|
@@ -478,7 +502,7 @@ export function houseNotifications(transport, mode) {
|
|
|
478
502
|
void loaded
|
|
479
503
|
.then(() => Promise.all(rooms.map(restored)))
|
|
480
504
|
.then((presented) => {
|
|
481
|
-
current.hold(presented, runtime
|
|
505
|
+
current.hold(presented, runtime);
|
|
482
506
|
for (const [index, room] of presented.entries()) {
|
|
483
507
|
if (room.position === rooms[index].position)
|
|
484
508
|
continue;
|
|
@@ -532,7 +556,18 @@ export function houseNotifications(transport, mode) {
|
|
|
532
556
|
held,
|
|
533
557
|
});
|
|
534
558
|
},
|
|
535
|
-
|
|
559
|
+
edited(tracked, from) {
|
|
560
|
+
const line = lines.get(tracked.authority);
|
|
561
|
+
const start = position(from.position);
|
|
562
|
+
if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
|
|
563
|
+
return [];
|
|
564
|
+
return [
|
|
565
|
+
...new Set(line.frames
|
|
566
|
+
.filter((frame) => frame.position > start)
|
|
567
|
+
.flatMap((frame) => frame.entries.flatMap((entry) => entry.kind === 'edited' && entry.revision !== undefined ? [entry.path] : []))),
|
|
568
|
+
];
|
|
569
|
+
},
|
|
570
|
+
*advance(tracked, from, holds) {
|
|
536
571
|
const line = lines.get(tracked.authority);
|
|
537
572
|
const start = position(from.position);
|
|
538
573
|
if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
|
|
@@ -541,36 +576,26 @@ export function houseNotifications(transport, mode) {
|
|
|
541
576
|
const first = pending[0];
|
|
542
577
|
if (first === undefined || first.after > start)
|
|
543
578
|
return null;
|
|
544
|
-
const
|
|
545
|
-
const revisions = {};
|
|
546
|
-
const changes = {};
|
|
547
|
-
const binaryFiles = {};
|
|
548
|
-
const removals = [];
|
|
549
|
-
const applied = [];
|
|
579
|
+
const answer = answering();
|
|
550
580
|
const schemas = new Map();
|
|
551
|
-
const forget = (path) => {
|
|
552
|
-
delete documents[path];
|
|
553
|
-
delete revisions[path];
|
|
554
|
-
delete changes[path];
|
|
555
|
-
delete binaryFiles[path];
|
|
556
|
-
const removed = removals.indexOf(path);
|
|
557
|
-
if (removed !== -1)
|
|
558
|
-
removals.splice(removed, 1);
|
|
559
|
-
};
|
|
560
581
|
for (const frame of pending) {
|
|
561
582
|
for (const entry of frame.entries) {
|
|
583
|
+
yield ROW_WEIGHT + (entry.text?.length ?? 0);
|
|
584
|
+
if (entry.kind === 'folder') {
|
|
585
|
+
folded(answer, entry.path, entry.removed === true);
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
562
588
|
if (entry.kind === 'edited' &&
|
|
563
589
|
entry.revision !== undefined &&
|
|
564
590
|
holds?.(entry.path, entry.revision) === true) {
|
|
565
|
-
|
|
591
|
+
forgotten(answer, entry.path);
|
|
566
592
|
continue;
|
|
567
593
|
}
|
|
568
|
-
|
|
569
|
-
if (tracked.schemas.includes(entry.path))
|
|
594
|
+
if (entry.path === tracked.schema)
|
|
570
595
|
schemas.set(entry.path, entry);
|
|
571
596
|
if (entry.kind === 'removed') {
|
|
572
|
-
|
|
573
|
-
removals.
|
|
597
|
+
forgotten(answer, entry.path);
|
|
598
|
+
answer.removals.add(entry.path);
|
|
574
599
|
continue;
|
|
575
600
|
}
|
|
576
601
|
const binary = binaryFileOf(entry);
|
|
@@ -581,31 +606,33 @@ export function houseNotifications(transport, mode) {
|
|
|
581
606
|
const head = headChange(entry);
|
|
582
607
|
if (head === null)
|
|
583
608
|
return null;
|
|
584
|
-
|
|
609
|
+
forgotten(answer, entry.path);
|
|
585
610
|
if (binary === undefined)
|
|
586
|
-
documents
|
|
611
|
+
answer.documents.set(entry.path, entry.text);
|
|
587
612
|
else
|
|
588
|
-
binaryFiles
|
|
613
|
+
answer.binaryFiles.set(entry.path, binary);
|
|
589
614
|
const revision = entry.revision ?? binary?.sha256;
|
|
590
615
|
if (revision !== undefined)
|
|
591
|
-
|
|
616
|
+
revised(answer, entry.path, revision);
|
|
592
617
|
if (head !== undefined)
|
|
593
|
-
changes
|
|
618
|
+
answer.changes.set(entry.path, head);
|
|
594
619
|
}
|
|
595
620
|
}
|
|
596
621
|
const last = pending.at(-1);
|
|
597
|
-
lines.
|
|
622
|
+
const current = lines.get(tracked.authority);
|
|
623
|
+
if (current?.logEpoch === line.logEpoch) {
|
|
624
|
+
lines.set(tracked.authority, {
|
|
625
|
+
...current,
|
|
626
|
+
frames: current.frames.filter((frame) => frame.position > start),
|
|
627
|
+
held: current.held !== null && current.held > last.position ? current.held : last.position,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
598
630
|
return {
|
|
599
631
|
page: {
|
|
600
632
|
kind: 'net-advancement',
|
|
601
633
|
roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),
|
|
602
|
-
|
|
603
|
-
revisions,
|
|
604
|
-
changes,
|
|
605
|
-
binaryFiles,
|
|
606
|
-
removals: removals.sort(),
|
|
634
|
+
...(yield* answered(answer)),
|
|
607
635
|
},
|
|
608
|
-
entries: applied,
|
|
609
636
|
schemas,
|
|
610
637
|
};
|
|
611
638
|
},
|
package/dist/transport.d.ts
CHANGED
|
@@ -15,27 +15,27 @@ export type HouseDoorAnswer = {
|
|
|
15
15
|
body: unknown;
|
|
16
16
|
};
|
|
17
17
|
export declare const DOOR_FILES_GET = "/door/files/get";
|
|
18
|
+
export declare const DOOR_FILES_ATTACH = "/door/files/attach";
|
|
19
|
+
export declare const DOOR_FILES_FINISH = "/door/files/finish";
|
|
18
20
|
export declare const SITE_FILES = "/_house/files/";
|
|
19
|
-
export
|
|
20
|
-
export type HouseByteAct = 'authored_batch_upload' | 'conversation_file_upload' | 'binary_stage';
|
|
21
|
-
export type HouseByteBody = string | ArrayBuffer | Uint8Array | Blob;
|
|
21
|
+
export type HouseByteAct = 'authored_batch_upload';
|
|
22
22
|
export type HouseBytesAnswer = {
|
|
23
23
|
status: number;
|
|
24
|
-
|
|
24
|
+
body: ReadableStream<Uint8Array> | null;
|
|
25
|
+
mediaType: string;
|
|
25
26
|
};
|
|
26
27
|
export type HouseByteTransfer = {
|
|
27
28
|
act: HouseByteAct;
|
|
28
29
|
url: string;
|
|
29
|
-
body:
|
|
30
|
-
operation?: string;
|
|
30
|
+
body: string;
|
|
31
31
|
};
|
|
32
32
|
export type HouseStreamEntry = {
|
|
33
33
|
path: string;
|
|
34
|
-
kind: 'edited' | 'removed' | 'piece';
|
|
34
|
+
kind: 'edited' | 'removed' | 'piece' | 'folder';
|
|
35
|
+
removed?: true;
|
|
35
36
|
revision?: string;
|
|
36
37
|
sha256?: string;
|
|
37
38
|
text?: string;
|
|
38
|
-
file?: string;
|
|
39
39
|
bytes?: number;
|
|
40
40
|
media_type?: string;
|
|
41
41
|
author?: {
|
|
@@ -58,6 +58,7 @@ export type HouseListedConversation = {
|
|
|
58
58
|
created_at: string;
|
|
59
59
|
finished_at: string | null;
|
|
60
60
|
outcome: string | null;
|
|
61
|
+
waiting: boolean;
|
|
61
62
|
};
|
|
62
63
|
export type HouseStreamFrame = {
|
|
63
64
|
type: 'part';
|
|
@@ -80,6 +81,9 @@ export type HouseStreamFrame = {
|
|
|
80
81
|
} | {
|
|
81
82
|
type: 'opening';
|
|
82
83
|
expired: readonly string[];
|
|
84
|
+
} | {
|
|
85
|
+
type: 'authority_changed';
|
|
86
|
+
rooms: readonly string[];
|
|
83
87
|
} | ({
|
|
84
88
|
type: 'turn';
|
|
85
89
|
conversation_id: string;
|
|
@@ -92,6 +96,10 @@ export type HouseStreamFrame = {
|
|
|
92
96
|
type: 'interactions';
|
|
93
97
|
conversation_id: string;
|
|
94
98
|
interactions: readonly unknown[];
|
|
99
|
+
} | {
|
|
100
|
+
type: 'deliveries';
|
|
101
|
+
conversation_id: string;
|
|
102
|
+
unknown: readonly string[];
|
|
95
103
|
} | {
|
|
96
104
|
type: 'process';
|
|
97
105
|
conversation_id: string;
|
|
@@ -104,6 +112,14 @@ export type HouseStreamFrame = {
|
|
|
104
112
|
type: 'options';
|
|
105
113
|
conversation_id: string;
|
|
106
114
|
options: LiveFact<'options'>['options'];
|
|
115
|
+
} | {
|
|
116
|
+
type: 'starting';
|
|
117
|
+
conversation_id: string;
|
|
118
|
+
step: string | null;
|
|
119
|
+
} | {
|
|
120
|
+
type: 'link';
|
|
121
|
+
conversation_id: string;
|
|
122
|
+
connected: boolean;
|
|
107
123
|
} | {
|
|
108
124
|
type: 'conversations';
|
|
109
125
|
conversations: readonly HouseListedConversation[];
|
|
@@ -134,31 +150,32 @@ export type HouseHeldRoom = {
|
|
|
134
150
|
log_epoch: string;
|
|
135
151
|
carry?: HouseHeldCarry;
|
|
136
152
|
};
|
|
137
|
-
export type HouseDemand = {
|
|
138
|
-
rooms: readonly string[];
|
|
139
|
-
conversations: boolean;
|
|
140
|
-
};
|
|
141
153
|
export type HouseOpening = {
|
|
142
|
-
hold(rooms: readonly HouseHeldRoom[], runtime: string
|
|
154
|
+
hold(rooms: readonly HouseHeldRoom[], runtime: string): void;
|
|
143
155
|
received(authority: string, carry: string, index: number): void;
|
|
144
156
|
close(): void;
|
|
145
157
|
};
|
|
158
|
+
export type HouseClosing = {
|
|
159
|
+
revoked: boolean;
|
|
160
|
+
lost: boolean;
|
|
161
|
+
};
|
|
146
162
|
export type HouseStream = {
|
|
147
163
|
observe(receive: (frame: HouseStreamFrame) => void): () => void;
|
|
148
164
|
opened(notify: (opening: HouseOpening) => void): () => void;
|
|
149
|
-
closed(notify: (
|
|
165
|
+
closed(notify: (closing: HouseClosing) => void): () => void;
|
|
150
166
|
};
|
|
151
167
|
export type HouseDoor = {
|
|
152
|
-
door(route: string, body: unknown): Promise<HouseDoorAnswer>;
|
|
168
|
+
door(route: string, body: unknown, arriving?: (bytes: number) => void): Promise<HouseDoorAnswer>;
|
|
153
169
|
stream: HouseStream;
|
|
154
170
|
};
|
|
155
171
|
export type HouseTransport = HouseDoor & {
|
|
156
172
|
transfer(request: HouseByteTransfer): Promise<HouseDoorAnswer>;
|
|
173
|
+
put(url: string, body: Blob, headers: Readonly<Record<string, string>>): Promise<number>;
|
|
157
174
|
download(url: string): Promise<HouseBytesAnswer>;
|
|
158
175
|
};
|
|
159
176
|
export type HouseSiteTransport = HouseDoor & {
|
|
160
177
|
online(): boolean;
|
|
161
|
-
read(route: string): Promise<HouseDoorAnswer>;
|
|
178
|
+
read(route: string, arriving?: (bytes: number) => void): Promise<HouseDoorAnswer>;
|
|
162
179
|
download(route: string): Promise<HouseBytesAnswer>;
|
|
163
180
|
};
|
|
164
181
|
export {};
|