@agentshouse/mdruntime-adapter 0.1.0-cd61dfca5d699 → 0.1.0-cd75dfaf57319
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 -66
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +7 -339
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +229 -371
- 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 +23 -14
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +92 -54
- package/dist/history.d.ts +12 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +92 -0
- package/dist/house-model.d.ts +719 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +393 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/model.d.ts +8 -3
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +37 -34
- package/dist/part.d.ts +14 -0
- package/dist/part.d.ts.map +1 -0
- package/dist/part.js +90 -0
- package/dist/read.d.ts +56 -63
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +240 -285
- package/dist/refusal.d.ts +0 -3
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +0 -5
- package/dist/room-stream.d.ts +20 -0
- package/dist/room-stream.d.ts.map +1 -0
- package/dist/room-stream.js +57 -0
- package/dist/room-types.d.ts +7 -0
- package/dist/room-types.d.ts.map +1 -0
- package/dist/room-types.js +123 -0
- package/dist/search.d.ts +5 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +47 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +88 -195
- package/dist/space-schema.d.ts +7 -0
- package/dist/space-schema.d.ts.map +1 -0
- package/dist/space-schema.js +18 -0
- package/dist/stream.d.ts +14 -14
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +170 -422
- package/dist/transport.d.ts +55 -40
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +54 -11
- 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 +18 -2
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +105 -75
- package/package.json +8 -4
- package/AGENTS.md +0 -299
- package/dist/gather.d.ts +0 -4
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -45
- 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
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { manifestedModels, partModels } from './model.js';
|
|
2
|
+
import { roomFrames } from './part.js';
|
|
3
|
+
import { housePart, manifested, roomHead } from './read.js';
|
|
4
|
+
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
5
|
+
export function roomStreams(mode, spaces) {
|
|
6
|
+
const open = new Map();
|
|
7
|
+
let opened = 0;
|
|
8
|
+
async function head(entry, room, arriving, signal) {
|
|
9
|
+
const frames = roomFrames(room, arriving, signal);
|
|
10
|
+
const first = await frames();
|
|
11
|
+
if (first.kind !== 'frame')
|
|
12
|
+
return UNCERTAIN;
|
|
13
|
+
const held = await roomHead(first.payload, mode);
|
|
14
|
+
if (held === null || held.anchor !== entry.authority)
|
|
15
|
+
return UNCERTAIN;
|
|
16
|
+
const { models, seen } = await manifestedModels(held, entry, spaces);
|
|
17
|
+
opened += 1;
|
|
18
|
+
const id = String(opened);
|
|
19
|
+
open.set(id, { entry, head: held, frames, next: 1, seen });
|
|
20
|
+
signal?.addEventListener('abort', () => open.delete(id), { once: true });
|
|
21
|
+
return { ...manifested(held, `${id}:1`, models), bytes: first.bytes };
|
|
22
|
+
}
|
|
23
|
+
async function part(entry, token) {
|
|
24
|
+
const [id = '', at = ''] = token.split(':');
|
|
25
|
+
const room = open.get(id);
|
|
26
|
+
if (room === undefined || room.entry.locator !== entry.locator || String(room.next) !== at)
|
|
27
|
+
return UNCERTAIN;
|
|
28
|
+
const frame = await room.frames();
|
|
29
|
+
if (frame.kind !== 'frame') {
|
|
30
|
+
open.delete(id);
|
|
31
|
+
return UNCERTAIN;
|
|
32
|
+
}
|
|
33
|
+
const read = await housePart(room.head, frame.payload, mode);
|
|
34
|
+
if ('kind' in read) {
|
|
35
|
+
open.delete(id);
|
|
36
|
+
return read;
|
|
37
|
+
}
|
|
38
|
+
const { scope, ended } = read;
|
|
39
|
+
const first = room.next === 1;
|
|
40
|
+
room.next += 1;
|
|
41
|
+
room.seen = [
|
|
42
|
+
...room.seen,
|
|
43
|
+
...(scope.files.some((file) => file.path === entry.schema) ? [entry.schema] : []),
|
|
44
|
+
];
|
|
45
|
+
if (ended)
|
|
46
|
+
open.delete(id);
|
|
47
|
+
return {
|
|
48
|
+
scope,
|
|
49
|
+
first,
|
|
50
|
+
ended,
|
|
51
|
+
models: await partModels(scope, entry, new Set(room.seen), ended),
|
|
52
|
+
pageToken: ended ? undefined : `${id}:${room.next}`,
|
|
53
|
+
bytes: frame.bytes,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return { head, part };
|
|
57
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const INBOX_CHANNEL_KINDS: readonly ['telegram-bot', 'telegram-business', 'whatsapp', 'messenger', 'instagram', 'viber', 'tiktok'];
|
|
2
|
+
export type InboxChannelKind = (typeof INBOX_CHANNEL_KINDS)[number];
|
|
3
|
+
export declare const CHAT_TYPE = "chat";
|
|
4
|
+
export declare const CHAT_MESSAGE_TYPE = "chat-message";
|
|
5
|
+
export declare const HOUSE_NAMEABLE_ROOM_TYPES: string[];
|
|
6
|
+
export declare const HOUSE_ROOM_TYPES: string;
|
|
7
|
+
//# sourceMappingURL=room-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-types.d.ts","sourceRoot":"","sources":["../src/room-types.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB,YAC9B,cAAc,EACd,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,QAAQ,CACA,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,SAAS,SAAS,CAAC;AAEhC,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD,eAAO,MAAM,yBAAyB,UAAiC,CAAC;AAyBxE,eAAO,MAAM,gBAAgB,QA2FjB,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { APP_REFERENCE_PATTERN } from './app-reference.js';
|
|
2
|
+
import { HOUSE_MODEL_TYPES } from './house-model.js';
|
|
3
|
+
export const INBOX_CHANNEL_KINDS = [
|
|
4
|
+
'telegram-bot',
|
|
5
|
+
'telegram-business',
|
|
6
|
+
'whatsapp',
|
|
7
|
+
'messenger',
|
|
8
|
+
'instagram',
|
|
9
|
+
'viber',
|
|
10
|
+
'tiktok',
|
|
11
|
+
];
|
|
12
|
+
export const CHAT_TYPE = 'chat';
|
|
13
|
+
export const CHAT_MESSAGE_TYPE = 'chat-message';
|
|
14
|
+
export const HOUSE_NAMEABLE_ROOM_TYPES = [CHAT_TYPE, CHAT_MESSAGE_TYPE];
|
|
15
|
+
const WAYFINDING_MAP_TYPE = 'wayfinding-map';
|
|
16
|
+
const WAYFINDING_TICKET_TYPE = 'wayfinding-ticket';
|
|
17
|
+
const WAYFINDING_MAP_SECTIONS = [
|
|
18
|
+
'Destination',
|
|
19
|
+
'Notes',
|
|
20
|
+
'Decisions so far',
|
|
21
|
+
'Not yet specified',
|
|
22
|
+
'Out of scope',
|
|
23
|
+
];
|
|
24
|
+
const IDENTITY = "{ type: string, pattern: '^\\S+$' }";
|
|
25
|
+
const AGENT = [' agent: { type: string, format: uuid }', ' name: { type: string }'];
|
|
26
|
+
const ASSIGNEE = [
|
|
27
|
+
' type: object',
|
|
28
|
+
' properties:',
|
|
29
|
+
' user: { type: string, format: uuid }',
|
|
30
|
+
...AGENT,
|
|
31
|
+
];
|
|
32
|
+
export const HOUSE_ROOM_TYPES = [
|
|
33
|
+
`${CHAT_TYPE}:`,
|
|
34
|
+
' properties:',
|
|
35
|
+
' inbox: { type: string, format: uuid }',
|
|
36
|
+
` channel: { enum: [${INBOX_CHANNEL_KINDS.join(', ')}] }`,
|
|
37
|
+
` chat: ${IDENTITY}`,
|
|
38
|
+
' customer:',
|
|
39
|
+
' type: object',
|
|
40
|
+
' properties:',
|
|
41
|
+
' name: { type: string }',
|
|
42
|
+
` username: ${IDENTITY}`,
|
|
43
|
+
` phone: ${IDENTITY}`,
|
|
44
|
+
' assignee:',
|
|
45
|
+
...ASSIGNEE,
|
|
46
|
+
' return_to:',
|
|
47
|
+
' type: object',
|
|
48
|
+
' properties:',
|
|
49
|
+
...AGENT,
|
|
50
|
+
' required: [chat, customer]',
|
|
51
|
+
`${CHAT_MESSAGE_TYPE}:`,
|
|
52
|
+
' properties:',
|
|
53
|
+
' direction: { enum: [in, out] }',
|
|
54
|
+
' sender:',
|
|
55
|
+
' type: object',
|
|
56
|
+
' properties:',
|
|
57
|
+
' name: { type: string }',
|
|
58
|
+
` username: ${IDENTITY}`,
|
|
59
|
+
' sent_at: { type: string, format: date-time }',
|
|
60
|
+
` channel_message: ${IDENTITY}`,
|
|
61
|
+
' labelled: { const: true }',
|
|
62
|
+
' reactions:',
|
|
63
|
+
' type: array',
|
|
64
|
+
' items:',
|
|
65
|
+
' type: object',
|
|
66
|
+
' properties:',
|
|
67
|
+
' reaction: { type: string, minLength: 1 }',
|
|
68
|
+
' sender:',
|
|
69
|
+
' type: object',
|
|
70
|
+
' properties:',
|
|
71
|
+
` id: ${IDENTITY}`,
|
|
72
|
+
' name: { type: string }',
|
|
73
|
+
` username: ${IDENTITY}`,
|
|
74
|
+
' count: { type: integer, minimum: 1 }',
|
|
75
|
+
' required: [reaction]',
|
|
76
|
+
` post: ${IDENTITY}`,
|
|
77
|
+
' assignee:',
|
|
78
|
+
...ASSIGNEE,
|
|
79
|
+
' sent_outside: { const: true }',
|
|
80
|
+
' template:',
|
|
81
|
+
' type: object',
|
|
82
|
+
' properties:',
|
|
83
|
+
' name: { type: string, minLength: 1 }',
|
|
84
|
+
' language: { type: string, minLength: 1 }',
|
|
85
|
+
' required: [name, language]',
|
|
86
|
+
' values:',
|
|
87
|
+
' type: object',
|
|
88
|
+
' additionalProperties: { type: string }',
|
|
89
|
+
' withheld: { const: true }',
|
|
90
|
+
' required: [direction]',
|
|
91
|
+
' if: { properties: { direction: { const: in } } }',
|
|
92
|
+
' then: { required: [sent_at] }',
|
|
93
|
+
`${WAYFINDING_MAP_TYPE}:`,
|
|
94
|
+
' properties:',
|
|
95
|
+
' title: { type: string }',
|
|
96
|
+
' required: [title]',
|
|
97
|
+
' sections:',
|
|
98
|
+
...WAYFINDING_MAP_SECTIONS.map((name) => ` ${name}: { kind: text, required: true }`),
|
|
99
|
+
`${WAYFINDING_TICKET_TYPE}:`,
|
|
100
|
+
' properties:',
|
|
101
|
+
' title: { type: string }',
|
|
102
|
+
' kind: { enum: [research, prototype, grilling, task] }',
|
|
103
|
+
' status: { enum: [open, in-progress, done, out-of-scope] }',
|
|
104
|
+
` map: { type: string, reference: ${WAYFINDING_MAP_TYPE} }`,
|
|
105
|
+
` blocked_by: { type: array, items: { type: string, reference: ${WAYFINDING_TICKET_TYPE} } }`,
|
|
106
|
+
' assignee:',
|
|
107
|
+
...ASSIGNEE,
|
|
108
|
+
' conversation: { type: string, format: uuid }',
|
|
109
|
+
` app: { type: string, pattern: '${APP_REFERENCE_PATTERN.source}' }`,
|
|
110
|
+
' required: [title, kind, status, map, blocked_by]',
|
|
111
|
+
' sections:',
|
|
112
|
+
' Question: { kind: text }',
|
|
113
|
+
' Answer: { kind: text }',
|
|
114
|
+
' allOf:',
|
|
115
|
+
' - if: { properties: { status: { enum: [in-progress, done, out-of-scope] } }, required: [status] }',
|
|
116
|
+
' then: { required: [assignee] }',
|
|
117
|
+
' else: { properties: { assignee: false } }',
|
|
118
|
+
' - if: { properties: { assignee: { required: [agent] } }, required: [assignee] }',
|
|
119
|
+
' else: { properties: { conversation: false } }',
|
|
120
|
+
' - if: { properties: { status: { enum: [done, out-of-scope] } }, required: [status] }',
|
|
121
|
+
' then: { sections: { Answer: { kind: text, required: true } } }',
|
|
122
|
+
HOUSE_MODEL_TYPES,
|
|
123
|
+
].join('\n');
|
package/dist/search.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SearchAnswer, SearchAsk } from '@agentshouse/mdruntime';
|
|
2
|
+
import type { TrackedAuthority } from './discovery.js';
|
|
3
|
+
import { type HouseTransport } from './transport.js';
|
|
4
|
+
export declare function houseSearch(transport: Pick<HouseTransport, 'door'>, tracked: readonly TrackedAuthority[], request: SearchAsk): Promise<SearchAnswer>;
|
|
5
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAa,MAAM,wBAAwB,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAsBrE,wBAAsB,WAAW,CAC/B,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,EACvC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,YAAY,CAAC,CAoBvB"}
|
package/dist/search.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { doorRefusal } from './refusal.js';
|
|
2
|
+
import { houseDoorRoute } from './transport.js';
|
|
3
|
+
const ROOMS = '/rooms/';
|
|
4
|
+
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
5
|
+
function hitOf(file, locators) {
|
|
6
|
+
if (typeof file !== 'object' || file === null)
|
|
7
|
+
return null;
|
|
8
|
+
const { path, line, snippet } = file;
|
|
9
|
+
if (typeof path !== 'string' || !path.startsWith(ROOMS))
|
|
10
|
+
return null;
|
|
11
|
+
const slash = path.indexOf('/', ROOMS.length);
|
|
12
|
+
if (slash < 0)
|
|
13
|
+
return null;
|
|
14
|
+
const room = locators.get(path.slice(ROOMS.length, slash));
|
|
15
|
+
if (room === undefined)
|
|
16
|
+
return null;
|
|
17
|
+
return {
|
|
18
|
+
room,
|
|
19
|
+
path: path.slice(slash + 1),
|
|
20
|
+
...(typeof line === 'number' ? { line } : {}),
|
|
21
|
+
...(typeof snippet === 'string' ? { snippet } : {}),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export async function houseSearch(transport, tracked, request) {
|
|
25
|
+
const named = request.rooms === null
|
|
26
|
+
? null
|
|
27
|
+
: tracked.filter((entry) => request.rooms.includes(entry.locator));
|
|
28
|
+
if (named !== null && named.length === 0)
|
|
29
|
+
return { kind: 'found', documents: [] };
|
|
30
|
+
const answer = await transport.door(houseDoorRoute('search'), {
|
|
31
|
+
query: request.text,
|
|
32
|
+
...(named === null ? {} : { paths: named.map((entry) => `${ROOMS}${entry.handle}`) }),
|
|
33
|
+
});
|
|
34
|
+
if (answer.status === 401)
|
|
35
|
+
return { kind: 'revoked-authorization' };
|
|
36
|
+
const refusal = doorRefusal(answer.body);
|
|
37
|
+
if (refusal !== null)
|
|
38
|
+
return { kind: 'rejected', ...refusal };
|
|
39
|
+
const files = answer.body?.files;
|
|
40
|
+
if (answer.status !== 200 || !Array.isArray(files))
|
|
41
|
+
return UNCERTAIN;
|
|
42
|
+
const locators = new Map(tracked.map((entry) => [entry.handle, entry.locator]));
|
|
43
|
+
return {
|
|
44
|
+
kind: 'found',
|
|
45
|
+
documents: files.flatMap((file) => hitOf(file, locators) ?? []),
|
|
46
|
+
};
|
|
47
|
+
}
|
package/dist/site.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,
|
|
1
|
+
{"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAQR,MAAM,wBAAwB,CAAC;AAiBhC,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAC;AAuBxB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,kBAAkB,EAAE,QAAQ,UAAQ,GAAG,OAAO,CA6K1F"}
|
package/dist/site.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { stepped } from '@agentshouse/mdruntime';
|
|
2
|
+
import { actionOutcome } from './actions.js';
|
|
2
3
|
import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteTracked, } from './discovery.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { classifyDoor,
|
|
4
|
+
import { bootstrapping } from './read.js';
|
|
5
|
+
import { roomStreams } from './room-stream.js';
|
|
6
|
+
import { spaceSchemas } from './space-schema.js';
|
|
7
|
+
import { classifyDoor, discoveryFailure } from './refusal.js';
|
|
8
|
+
import { HOUSE_TYPED_PATHS } from './house-model.js';
|
|
9
|
+
import { HOUSE_NAMEABLE_ROOM_TYPES, HOUSE_ROOM_TYPES } from './room-types.js';
|
|
7
10
|
import { houseNotifications } from './stream.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
|
|
11
|
+
import { houseSiteRoute, SITE_DOOR_SUBMIT, SITE_FILES, SITE_SUBMISSION, } from './transport.js';
|
|
12
|
+
import { followsVersion, logPosition, presented, reachedVersion, roomVersion } from './version.js';
|
|
11
13
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
12
14
|
function unfound() {
|
|
13
15
|
return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
|
|
@@ -18,197 +20,104 @@ function siteRoom(tracked) {
|
|
|
18
20
|
locator: tracked.locator,
|
|
19
21
|
handle: tracked.handle,
|
|
20
22
|
roomVersion: roomVersion(tracked),
|
|
21
|
-
operations: {
|
|
22
|
-
replica: { selection: tracked.locator, admission: 'admitted' },
|
|
23
|
+
operations: { write: [], erase: [] },
|
|
24
|
+
replica: { selection: tracked.locator, admission: 'admitted', offline: 'open' },
|
|
23
25
|
providerOwnedPaths: [],
|
|
24
26
|
};
|
|
25
27
|
}
|
|
26
|
-
function settled(refused) {
|
|
27
|
-
return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;
|
|
28
|
-
}
|
|
29
28
|
export function createSiteAdapter(transport, snapshot = false) {
|
|
30
|
-
const
|
|
29
|
+
const spaces = spaceSchemas();
|
|
30
|
+
const notifications = houseNotifications(transport, 'site', {
|
|
31
|
+
opened: async () => {
|
|
32
|
+
const found = await discovered();
|
|
33
|
+
return found.kind === 'discovery' ? found : null;
|
|
34
|
+
},
|
|
35
|
+
changed: () => null,
|
|
36
|
+
}, spaces);
|
|
31
37
|
const tracked = new Map();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return named === null || !tracked.has(named.locator) ? null : named;
|
|
35
|
-
}
|
|
38
|
+
const read = new Map();
|
|
39
|
+
const rooms = roomStreams('site', spaces);
|
|
36
40
|
function fileRoute(request) {
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
39
|
-
return { kind: '
|
|
40
|
-
}
|
|
41
|
-
if (request.fileRef === undefined)
|
|
42
|
-
return unfound();
|
|
43
|
-
const { room_ref, path, record } = named.referrer;
|
|
44
|
-
return `${SITE_FILES}${room_ref}/${encodeURIComponent(request.fileRef)}/${path === undefined
|
|
45
|
-
? `${SITE_FILE_RECORD}/${encodeURIComponent(record)}`
|
|
46
|
-
: encodeURIComponent(path)}`;
|
|
41
|
+
const entry = tracked.get(request.locator);
|
|
42
|
+
if (entry === undefined)
|
|
43
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
44
|
+
return `${SITE_FILES}${entry.authority}/${encodeURIComponent(request.revision)}/${encodeURIComponent(request.path)}`;
|
|
47
45
|
}
|
|
48
|
-
async function
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
const classified = classifyRead(answer.status, answer.body, entry.locator);
|
|
60
|
-
if (classified !== null)
|
|
61
|
-
return classified;
|
|
62
|
-
const found = parseEnumeration(answer.body, 'site');
|
|
63
|
-
if (found === null)
|
|
64
|
-
return UNCERTAIN;
|
|
65
|
-
return viewOf(found, entry) ?? { kind: 'room-not-readable', locator: entry.locator };
|
|
46
|
+
async function openedRoom(entry, arriving, signal) {
|
|
47
|
+
const cut = read.get(entry.locator);
|
|
48
|
+
const answered = await transport.streamed(`${houseSiteRoute('bootstrap')}/${entry.authority}${cut === undefined ? '' : `?expired=${cut}`}`, signal ?? new AbortController().signal);
|
|
49
|
+
if (answered.room === null)
|
|
50
|
+
return classifyDoor(answered.status, answered.body, entry.locator) ?? UNCERTAIN;
|
|
51
|
+
const head = await rooms.head(entry, answered.room, arriving, signal);
|
|
52
|
+
const at = head.kind === 'bootstrap' ? logPosition(head.roomVersion) : null;
|
|
53
|
+
if (at !== null)
|
|
54
|
+
read.set(entry.locator, at.position);
|
|
55
|
+
return head;
|
|
66
56
|
}
|
|
67
|
-
async function
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
async function bootstrapPart(entry, after, offset) {
|
|
72
|
-
const query = [
|
|
73
|
-
...(after === null ? [] : [`after=${encodeURIComponent(after)}`]),
|
|
74
|
-
...(offset === null ? [] : [`offset=${offset}`]),
|
|
75
|
-
];
|
|
76
|
-
const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}${query.length === 0 ? '' : `?${query.join('&')}`}`);
|
|
77
|
-
const classified = classifyDoor(answer.status, answer.body, entry.locator);
|
|
78
|
-
if (classified !== null)
|
|
79
|
-
return { failure: classified };
|
|
80
|
-
const scope = parseSiteBootstrap(answer.body);
|
|
81
|
-
return scope === null ? { failure: UNCERTAIN } : { body: answer.body, scope };
|
|
82
|
-
}
|
|
83
|
-
async function assembled(entry, scope, path, offset) {
|
|
84
|
-
const opened = scope.contents.at(-1);
|
|
85
|
-
if (opened === undefined || opened.path !== path || opened.content.length !== offset) {
|
|
86
|
-
return UNCERTAIN;
|
|
87
|
-
}
|
|
88
|
-
let text = opened.content;
|
|
89
|
-
for (;;) {
|
|
90
|
-
const part = await bootstrapPart(entry, path, text.length);
|
|
91
|
-
if ('failure' in part)
|
|
92
|
-
return part.failure;
|
|
93
|
-
const [piece] = part.scope.contents;
|
|
94
|
-
if (piece === undefined ||
|
|
95
|
-
part.scope.contents.length !== 1 ||
|
|
96
|
-
piece.path !== path ||
|
|
97
|
-
piece.content.length === 0) {
|
|
98
|
-
return UNCERTAIN;
|
|
99
|
-
}
|
|
100
|
-
text += piece.content;
|
|
101
|
-
const more = siteBootstrapOffset(part.body);
|
|
102
|
-
if (more === null)
|
|
103
|
-
break;
|
|
104
|
-
if (more !== text.length)
|
|
105
|
-
return UNCERTAIN;
|
|
106
|
-
}
|
|
107
|
-
const file = scope.files.find((held) => held.path === path);
|
|
108
|
-
if (file === undefined || (await sha256Hex(text)) !== file.version)
|
|
109
|
-
return UNCERTAIN;
|
|
110
|
-
return { ...scope, contents: [...scope.contents.slice(0, -1), { path, content: text }] };
|
|
111
|
-
}
|
|
112
|
-
async function caughtUp(entry, after) {
|
|
113
|
-
const part = await bootstrapPart(entry, after, null);
|
|
114
|
-
if ('failure' in part)
|
|
57
|
+
async function streamedPage(entry, token) {
|
|
58
|
+
const part = await rooms.part(entry, token);
|
|
59
|
+
if ('kind' in part)
|
|
115
60
|
return part;
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
const { scope } = part;
|
|
125
|
-
if (after !== null || next !== null || roomVersion(scope) === roomVersion(entry)) {
|
|
126
|
-
return { scope, next };
|
|
127
|
-
}
|
|
128
|
-
const view = await enumeration(entry, scope);
|
|
129
|
-
if ('kind' in view)
|
|
130
|
-
return { failure: settled(view) };
|
|
131
|
-
return { scope: advancedScope(scope, view), next: null };
|
|
61
|
+
const { folders: _folders, ...page } = await stepped(bootstrapping(part.scope));
|
|
62
|
+
return {
|
|
63
|
+
...page,
|
|
64
|
+
...(part.models === undefined ? {} : { models: part.models }),
|
|
65
|
+
...(part.pageToken === undefined ? {} : { pageToken: part.pageToken }),
|
|
66
|
+
bytes: part.bytes,
|
|
67
|
+
};
|
|
132
68
|
}
|
|
133
|
-
async function
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
notifications.
|
|
146
|
-
|
|
147
|
-
if (answer.kind !== 'net-advancement')
|
|
148
|
-
return answer;
|
|
149
|
-
const models = await viewModels(view, entry);
|
|
150
|
-
return models === undefined ? answer : { ...answer, models };
|
|
69
|
+
async function discovered() {
|
|
70
|
+
const answer = await transport.read(houseSiteRoute('discover'));
|
|
71
|
+
const failed = discoveryFailure(answer.status, answer.body);
|
|
72
|
+
if (failed !== null)
|
|
73
|
+
return failed;
|
|
74
|
+
const document = parseSiteDiscovery(answer.body);
|
|
75
|
+
if (document === null)
|
|
76
|
+
return UNCERTAIN;
|
|
77
|
+
const entries = siteTracked(document);
|
|
78
|
+
tracked.clear();
|
|
79
|
+
for (const entry of entries)
|
|
80
|
+
tracked.set(entry.locator, entry);
|
|
81
|
+
notifications.track(entries);
|
|
82
|
+
return mapDiscovery(document, entries.map(siteRoom), siteCapabilities());
|
|
151
83
|
}
|
|
152
84
|
return {
|
|
153
85
|
localSaves: true,
|
|
154
|
-
|
|
86
|
+
roomTypes: HOUSE_ROOM_TYPES,
|
|
87
|
+
nameableRoomTypes: HOUSE_NAMEABLE_ROOM_TYPES,
|
|
88
|
+
typedPaths: HOUSE_TYPED_PATHS,
|
|
155
89
|
async authorize() {
|
|
156
90
|
return {};
|
|
157
91
|
},
|
|
158
|
-
async discover() {
|
|
159
|
-
const answer = await transport.read(SITE_DOOR_DISCOVER);
|
|
160
|
-
const failed = discoveryFailure(answer.status, answer.body);
|
|
161
|
-
if (failed !== null)
|
|
162
|
-
return failed;
|
|
163
|
-
const document = parseSiteDiscovery(answer.body);
|
|
164
|
-
if (document === null)
|
|
165
|
-
return UNCERTAIN;
|
|
166
|
-
const entries = siteTracked(document);
|
|
167
|
-
tracked.clear();
|
|
168
|
-
for (const entry of entries)
|
|
169
|
-
tracked.set(entry.locator, entry);
|
|
170
|
-
notifications.track(entries);
|
|
171
|
-
return mapDiscovery(document, entries.map(siteRoom), siteCapabilities());
|
|
172
|
-
},
|
|
173
92
|
async bootstrap(_authorization, request) {
|
|
174
93
|
const entry = tracked.get(request.locator);
|
|
175
94
|
if (entry === undefined)
|
|
176
95
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
177
|
-
|
|
178
|
-
?
|
|
179
|
-
:
|
|
180
|
-
const held = await caughtUp(entry, continued?.after ?? null);
|
|
181
|
-
if ('failure' in held)
|
|
182
|
-
return held.failure;
|
|
183
|
-
notifications.reach(entry.authority, held.scope);
|
|
184
|
-
const seen = [
|
|
185
|
-
...(continued?.seen ?? []),
|
|
186
|
-
...entry.schemas.filter((schema) => held.scope.files.some((file) => file.path === schema)),
|
|
187
|
-
];
|
|
188
|
-
const models = await partModels(held.scope, entry, new Set(seen), held.next === null);
|
|
189
|
-
const continuation = held.next === null ? null : { after: held.next, seen };
|
|
190
|
-
return {
|
|
191
|
-
...bootstrapOf(held.scope),
|
|
192
|
-
...(models === undefined ? {} : { models }),
|
|
193
|
-
...(continuation === null ? {} : { pageToken: JSON.stringify(continuation) }),
|
|
194
|
-
};
|
|
96
|
+
return request.pageToken === undefined
|
|
97
|
+
? openedRoom(entry, request.arriving, request.signal)
|
|
98
|
+
: streamedPage(entry, request.pageToken);
|
|
195
99
|
},
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
100
|
+
...(snapshot
|
|
101
|
+
? {
|
|
102
|
+
discover: discovered,
|
|
103
|
+
async refresh(_authorization, request) {
|
|
104
|
+
const entry = tracked.get(request.locator);
|
|
105
|
+
if (entry === undefined)
|
|
106
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
107
|
+
if (request.pageToken !== undefined)
|
|
108
|
+
return UNCERTAIN;
|
|
109
|
+
return request.fromRoomVersion === roomVersion(entry)
|
|
110
|
+
? { kind: 'still-current' }
|
|
111
|
+
: { kind: 'beyond-horizon' };
|
|
112
|
+
},
|
|
206
113
|
}
|
|
207
|
-
|
|
208
|
-
},
|
|
114
|
+
: {}),
|
|
209
115
|
async mutate() {
|
|
210
116
|
return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {}, retryable: false };
|
|
211
117
|
},
|
|
118
|
+
async attach() {
|
|
119
|
+
return { kind: 'rejected', code: 'write-grant', fields: {}, retryable: false };
|
|
120
|
+
},
|
|
212
121
|
async history() {
|
|
213
122
|
return { kind: 'no-history' };
|
|
214
123
|
},
|
|
@@ -219,8 +128,8 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
219
128
|
const read = await transport.download(route);
|
|
220
129
|
if (read.status === 404)
|
|
221
130
|
return unfound();
|
|
222
|
-
return read.status === 200 && read.
|
|
223
|
-
? { kind: 'binary',
|
|
131
|
+
return read.status === 200 && read.body !== null
|
|
132
|
+
? { kind: 'binary', body: read.body, mediaType: read.mediaType }
|
|
224
133
|
: UNCERTAIN;
|
|
225
134
|
},
|
|
226
135
|
async link(_authorization, request) {
|
|
@@ -233,13 +142,6 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
233
142
|
name: request.path.slice(request.path.lastIndexOf('/') + 1),
|
|
234
143
|
};
|
|
235
144
|
},
|
|
236
|
-
referrerScope(referrer) {
|
|
237
|
-
const named = published(referrer);
|
|
238
|
-
if (named === null)
|
|
239
|
-
return null;
|
|
240
|
-
const { path } = named.referrer;
|
|
241
|
-
return { kind: 'room', locator: named.locator, ...(path === undefined ? {} : { path }) };
|
|
242
|
-
},
|
|
243
145
|
reached(locator, version, target) {
|
|
244
146
|
return reachedVersion(version, target, tracked.get(locator)?.logEpoch);
|
|
245
147
|
},
|
|
@@ -247,7 +149,7 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
247
149
|
return followsVersion(version, next);
|
|
248
150
|
},
|
|
249
151
|
async action(_authorization, request) {
|
|
250
|
-
if (request.name !==
|
|
152
|
+
if (request.name !== SITE_SUBMISSION) {
|
|
251
153
|
return {
|
|
252
154
|
kind: 'rejected',
|
|
253
155
|
code: 'action-unimplemented',
|
|
@@ -257,7 +159,7 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
257
159
|
}
|
|
258
160
|
if (!transport.online())
|
|
259
161
|
return UNCERTAIN;
|
|
260
|
-
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input),
|
|
162
|
+
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input), SITE_SUBMISSION, request.input);
|
|
261
163
|
},
|
|
262
164
|
roomStream: snapshot
|
|
263
165
|
? undefined
|
|
@@ -266,19 +168,10 @@ export function createSiteAdapter(transport, snapshot = false) {
|
|
|
266
168
|
notifications.send(rooms.flatMap((room) => {
|
|
267
169
|
const entry = tracked.get(room.locator);
|
|
268
170
|
const at = logPosition(room.roomVersion);
|
|
269
|
-
|
|
270
|
-
return [];
|
|
271
|
-
notifications.reach(entry.authority, at);
|
|
272
|
-
return [presented(entry.authority, at)];
|
|
171
|
+
return entry === undefined || at === null ? [] : [presented(entry.authority, at)];
|
|
273
172
|
}));
|
|
274
173
|
},
|
|
275
|
-
reopen: notifications.reopen,
|
|
276
174
|
observe: notifications.observe,
|
|
277
|
-
published(locator, roomVersion) {
|
|
278
|
-
const at = logPosition(roomVersion);
|
|
279
|
-
if (at !== null)
|
|
280
|
-
notifications.published(locator, at);
|
|
281
|
-
},
|
|
282
175
|
},
|
|
283
176
|
serviceMode: notifications.serviceMode,
|
|
284
177
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type SpaceSchemas = {
|
|
2
|
+
held(space: string, revision: string): string | undefined;
|
|
3
|
+
keep(space: string, revision: string, text: string): void;
|
|
4
|
+
};
|
|
5
|
+
export declare function spaceSchemas(): SpaceSchemas;
|
|
6
|
+
export declare function spaceIdentity(space: string): string;
|
|
7
|
+
//# sourceMappingURL=space-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space-schema.d.ts","sourceRoot":"","sources":["../src/space-schema.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3D,CAAC;AAEF,wBAAgB,YAAY,IAAI,YAAY,CAY3C;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const HELD_TEXTS = 16;
|
|
2
|
+
export function spaceSchemas() {
|
|
3
|
+
const texts = new Map();
|
|
4
|
+
const key = (space, revision) => `${space} ${revision}`;
|
|
5
|
+
return {
|
|
6
|
+
held: (space, revision) => texts.get(key(space, revision)),
|
|
7
|
+
keep(space, revision, text) {
|
|
8
|
+
const named = key(space, revision);
|
|
9
|
+
texts.delete(named);
|
|
10
|
+
texts.set(named, text);
|
|
11
|
+
if (texts.size > HELD_TEXTS)
|
|
12
|
+
texts.delete(texts.keys().next().value);
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function spaceIdentity(space) {
|
|
17
|
+
return `space:${space}`;
|
|
18
|
+
}
|