@agentshouse/mdruntime-adapter 0.1.0-alpha.3 → 0.1.0-alpha.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +122 -22
- package/dist/actions.d.ts +3 -11
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +119 -224
- package/dist/actions.js.map +1 -1
- package/dist/adapter.d.ts +3 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +48 -104
- package/dist/adapter.js.map +1 -1
- package/dist/discovery.d.ts +35 -8
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +136 -32
- package/dist/discovery.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/model.d.ts +19 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +64 -0
- package/dist/model.js.map +1 -0
- package/dist/read.d.ts +20 -15
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +118 -39
- package/dist/read.js.map +1 -1
- package/dist/refusal.d.ts +4 -1
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +13 -0
- package/dist/refusal.js.map +1 -1
- package/dist/site.d.ts +4 -0
- package/dist/site.d.ts.map +1 -0
- package/dist/site.js +205 -0
- package/dist/site.js.map +1 -0
- package/dist/stream.d.ts +6 -5
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +107 -119
- package/dist/stream.js.map +1 -1
- package/dist/transport.d.ts +16 -25
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +5 -1
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +14 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +29 -0
- package/dist/version.js.map +1 -0
- package/dist/write.d.ts +6 -0
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +24 -7
- package/dist/write.js.map +1 -1
- package/package.json +3 -3
package/dist/site.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { actionOutcome } from './actions.js';
|
|
2
|
+
import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteSlots, siteTracked } from './discovery.js';
|
|
3
|
+
import { MODEL_ABSENT, failedModel, heldModel, modelKey, modelShelf } from './model.js';
|
|
4
|
+
import { advancedScope, authorityRoot, bootstrapOf, definitionsOf, parseEnumeration, parseSiteBootstrap, refreshFrom, selectionRoots } from './read.js';
|
|
5
|
+
import { classifyDoor, discoveryFailure } from './refusal.js';
|
|
6
|
+
import { houseNotifications } from './stream.js';
|
|
7
|
+
import { PRIVATE_LOCATOR, SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT } from './transport.js';
|
|
8
|
+
import { logPosition, presented, roomVersion } from './version.js';
|
|
9
|
+
const UNCERTAIN = {
|
|
10
|
+
kind: 'transport-uncertainty'
|
|
11
|
+
};
|
|
12
|
+
function siteRoom(tracked, attachedModel) {
|
|
13
|
+
const read = selectionRoots(tracked);
|
|
14
|
+
return {
|
|
15
|
+
name: tracked.handle,
|
|
16
|
+
locator: tracked.locator,
|
|
17
|
+
collectionRoot: tracked.collectionRoot,
|
|
18
|
+
roomVersion: roomVersion(tracked),
|
|
19
|
+
operations: {
|
|
20
|
+
read: [
|
|
21
|
+
...read
|
|
22
|
+
],
|
|
23
|
+
sync: [
|
|
24
|
+
...read
|
|
25
|
+
],
|
|
26
|
+
write: [],
|
|
27
|
+
delete: []
|
|
28
|
+
},
|
|
29
|
+
replica: {
|
|
30
|
+
selection: tracked.locator,
|
|
31
|
+
admission: 'admitted'
|
|
32
|
+
},
|
|
33
|
+
attachedModel,
|
|
34
|
+
providerOwnedPaths: []
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function settled(refused) {
|
|
38
|
+
return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;
|
|
39
|
+
}
|
|
40
|
+
export function createSiteAdapter(transport) {
|
|
41
|
+
const notifications = houseNotifications(transport, 'site');
|
|
42
|
+
const tracked = new Map();
|
|
43
|
+
const models = modelShelf();
|
|
44
|
+
const acquired = new Map();
|
|
45
|
+
let caught = new Map();
|
|
46
|
+
async function enumeration(entry, from) {
|
|
47
|
+
const answer = await transport.door(SITE_DOOR_ENUMERATE, {
|
|
48
|
+
positions: [
|
|
49
|
+
presented(entry.authority, from)
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
const classified = classifyDoor(answer.status, answer.body, entry.locator);
|
|
53
|
+
if (classified !== null) return classified;
|
|
54
|
+
return parseEnumeration(answer.body, 'site') ?? UNCERTAIN;
|
|
55
|
+
}
|
|
56
|
+
async function caughtUp(entry) {
|
|
57
|
+
const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}`);
|
|
58
|
+
const classified = classifyDoor(answer.status, answer.body, entry.locator);
|
|
59
|
+
if (classified !== null) return {
|
|
60
|
+
failure: settled(classified)
|
|
61
|
+
};
|
|
62
|
+
const scope = parseSiteBootstrap(answer.body);
|
|
63
|
+
if (scope === null) return {
|
|
64
|
+
failure: UNCERTAIN
|
|
65
|
+
};
|
|
66
|
+
if (roomVersion(scope) === roomVersion(entry)) return {
|
|
67
|
+
scope
|
|
68
|
+
};
|
|
69
|
+
const found = await enumeration(entry, scope);
|
|
70
|
+
if ('kind' in found) return {
|
|
71
|
+
failure: settled(found)
|
|
72
|
+
};
|
|
73
|
+
const view = found.authorities.find((held)=>held.authority === entry.authority);
|
|
74
|
+
if (view === undefined) return {
|
|
75
|
+
failure: {
|
|
76
|
+
kind: 'room-not-readable',
|
|
77
|
+
locator: entry.locator
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
scope: advancedScope(scope, view)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function refreshed(entry, fromRoomVersion) {
|
|
85
|
+
const from = logPosition(fromRoomVersion);
|
|
86
|
+
if (from === null) return {
|
|
87
|
+
kind: 'beyond-horizon'
|
|
88
|
+
};
|
|
89
|
+
const streamed = notifications.advance(entry, from);
|
|
90
|
+
if (streamed !== null) return streamed;
|
|
91
|
+
const found = await enumeration(entry, from);
|
|
92
|
+
if ('kind' in found) return found;
|
|
93
|
+
return refreshFrom(found, entry, fromRoomVersion);
|
|
94
|
+
}
|
|
95
|
+
async function acquire(entry, held) {
|
|
96
|
+
if ('failure' in held) return {
|
|
97
|
+
snapshot: failedModel(held.failure),
|
|
98
|
+
identity: null
|
|
99
|
+
};
|
|
100
|
+
const model = await heldModel(definitionsOf(held.scope, entry.modelRoot), `${authorityRoot(entry.handle)}/${entry.modelRoot}`, MODEL_ABSENT);
|
|
101
|
+
acquired.set(entry.authority, {
|
|
102
|
+
roomVersion: roomVersion(held.scope),
|
|
103
|
+
model
|
|
104
|
+
});
|
|
105
|
+
return model;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
async authorize () {
|
|
109
|
+
return {};
|
|
110
|
+
},
|
|
111
|
+
async model (_authorization, request) {
|
|
112
|
+
return models.answer(request);
|
|
113
|
+
},
|
|
114
|
+
async discover () {
|
|
115
|
+
const answer = await transport.read(SITE_DOOR_DISCOVER);
|
|
116
|
+
const classified = classifyDoor(answer.status, answer.body, PRIVATE_LOCATOR);
|
|
117
|
+
if (classified !== null) return discoveryFailure(classified);
|
|
118
|
+
const document = parseSiteDiscovery(answer.body);
|
|
119
|
+
if (document === null) return UNCERTAIN;
|
|
120
|
+
const entries = siteTracked(document);
|
|
121
|
+
tracked.clear();
|
|
122
|
+
for (const entry of entries)tracked.set(entry.locator, entry);
|
|
123
|
+
notifications.track(entries);
|
|
124
|
+
const published = new Set(entries.map((entry)=>entry.authority));
|
|
125
|
+
for (const authority of [
|
|
126
|
+
...acquired.keys()
|
|
127
|
+
]){
|
|
128
|
+
if (!published.has(authority)) acquired.delete(authority);
|
|
129
|
+
}
|
|
130
|
+
const fresh = new Map();
|
|
131
|
+
const current = new Map();
|
|
132
|
+
for (const entry of entries){
|
|
133
|
+
const kept = acquired.get(entry.authority);
|
|
134
|
+
if (kept !== undefined && kept.roomVersion === roomVersion(entry)) {
|
|
135
|
+
current.set(entry.authority, kept.model);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const held = await caughtUp(entry);
|
|
139
|
+
fresh.set(entry.authority, held);
|
|
140
|
+
current.set(entry.authority, await acquire(entry, held));
|
|
141
|
+
}
|
|
142
|
+
caught = fresh;
|
|
143
|
+
const rooms = entries.map((entry)=>{
|
|
144
|
+
const shelved = models.retain(modelKey(entry.locator, 'collection'), current.get(entry.authority));
|
|
145
|
+
return siteRoom(entry, shelved?.identity ?? null);
|
|
146
|
+
});
|
|
147
|
+
models.keep(entries.map((entry)=>entry.locator));
|
|
148
|
+
return {
|
|
149
|
+
...mapDiscovery(document, rooms, siteCapabilities()),
|
|
150
|
+
slots: siteSlots(document)
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
async bootstrap (_authorization, request) {
|
|
154
|
+
const entry = tracked.get(request.locator);
|
|
155
|
+
if (entry === undefined) return {
|
|
156
|
+
kind: 'room-not-readable',
|
|
157
|
+
locator: request.locator
|
|
158
|
+
};
|
|
159
|
+
if (request.pageToken !== undefined) return UNCERTAIN;
|
|
160
|
+
const held = caught.get(entry.authority) ?? await caughtUp(entry);
|
|
161
|
+
if ('failure' in held) return held.failure;
|
|
162
|
+
return bootstrapOf(held.scope, entry);
|
|
163
|
+
},
|
|
164
|
+
async refresh (_authorization, request) {
|
|
165
|
+
const entry = tracked.get(request.locator);
|
|
166
|
+
if (entry === undefined) return {
|
|
167
|
+
kind: 'room-not-readable',
|
|
168
|
+
locator: request.locator
|
|
169
|
+
};
|
|
170
|
+
if (request.pageToken !== undefined) return UNCERTAIN;
|
|
171
|
+
const result = await refreshed(entry, request.fromRoomVersion);
|
|
172
|
+
if (result.kind === 'beyond-horizon') caught.delete(entry.authority);
|
|
173
|
+
return result;
|
|
174
|
+
},
|
|
175
|
+
async mutate () {
|
|
176
|
+
return {
|
|
177
|
+
kind: 'rejected',
|
|
178
|
+
affected: {},
|
|
179
|
+
code: 'write-grant',
|
|
180
|
+
fields: {}
|
|
181
|
+
};
|
|
182
|
+
},
|
|
183
|
+
async history () {
|
|
184
|
+
return {
|
|
185
|
+
kind: 'no-history'
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
async action (_authorization, request) {
|
|
189
|
+
if (request.name !== 'submit') {
|
|
190
|
+
return {
|
|
191
|
+
kind: 'rejected',
|
|
192
|
+
code: 'action-unimplemented',
|
|
193
|
+
fields: {
|
|
194
|
+
name: request.name
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (!transport.online()) return UNCERTAIN;
|
|
199
|
+
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input), 'submit');
|
|
200
|
+
},
|
|
201
|
+
roomVersions: notifications
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
//# sourceMappingURL=site.js.map
|
package/dist/site.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdruntime-adapter/src/site.ts"],"sourcesContent":["import type {\n Adapter,\n AdapterFailure,\n BootstrapResult,\n DiscoverResult,\n DiscoveredRoom,\n ModelResult,\n RefreshResult,\n} from '@agentshouse/mdruntime';\nimport { actionOutcome } from './actions.js';\nimport {\n mapDiscovery,\n parseSiteDiscovery,\n siteCapabilities,\n siteSlots,\n siteTracked,\n type SiteTracked,\n} from './discovery.js';\nimport {\n MODEL_ABSENT,\n failedModel,\n heldModel,\n modelKey,\n modelShelf,\n type HeldModel,\n} from './model.js';\nimport {\n advancedScope,\n authorityRoot,\n bootstrapOf,\n definitionsOf,\n parseEnumeration,\n parseSiteBootstrap,\n refreshFrom,\n selectionRoots,\n type HouseEnumeration,\n type HouseScope,\n} from './read.js';\nimport { classifyDoor, discoveryFailure } from './refusal.js';\nimport { houseNotifications } from './stream.js';\nimport {\n PRIVATE_LOCATOR,\n SITE_DOOR_BOOTSTRAP,\n SITE_DOOR_DISCOVER,\n SITE_DOOR_ENUMERATE,\n SITE_DOOR_SUBMIT,\n type HouseSiteTransport,\n} from './transport.js';\nimport { logPosition, presented, roomVersion, type LogPosition } from './version.js';\n\ntype Refused = AdapterFailure | { kind: 'beyond-horizon' };\n\ntype CaughtUp = { scope: HouseScope } | { failure: AdapterFailure };\n\ntype Acquired = { roomVersion: string; model: HeldModel };\n\nconst UNCERTAIN = { kind: 'transport-uncertainty' } as const;\n\nfunction siteRoom(\n tracked: SiteTracked,\n attachedModel: DiscoveredRoom['attachedModel'],\n): DiscoveredRoom {\n const read = selectionRoots(tracked);\n return {\n name: tracked.handle,\n locator: tracked.locator,\n collectionRoot: tracked.collectionRoot,\n roomVersion: roomVersion(tracked),\n operations: { read: [...read], sync: [...read], write: [], delete: [] },\n replica: { selection: tracked.locator, admission: 'admitted' },\n attachedModel,\n providerOwnedPaths: [],\n };\n}\n\nfunction settled(refused: Refused): AdapterFailure {\n return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;\n}\n\nexport function createSiteAdapter(transport: HouseSiteTransport): Adapter {\n const notifications = houseNotifications(transport, 'site');\n const tracked = new Map<string, SiteTracked>();\n const models = modelShelf();\n const acquired = new Map<string, Acquired>();\n let caught = new Map<string, CaughtUp>();\n\n async function enumeration(\n entry: SiteTracked,\n from: LogPosition,\n ): Promise<HouseEnumeration | Refused> {\n const answer = await transport.door(SITE_DOOR_ENUMERATE, {\n positions: [presented(entry.authority, from)],\n });\n const classified = classifyDoor(answer.status, answer.body, entry.locator);\n if (classified !== null) return classified;\n return parseEnumeration(answer.body, 'site') ?? UNCERTAIN;\n }\n\n async function caughtUp(entry: SiteTracked): Promise<CaughtUp> {\n const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}`);\n const classified = classifyDoor(answer.status, answer.body, entry.locator);\n if (classified !== null) return { failure: settled(classified) };\n const scope = parseSiteBootstrap(answer.body);\n if (scope === null) return { failure: UNCERTAIN };\n if (roomVersion(scope) === roomVersion(entry)) return { scope };\n const found = await enumeration(entry, scope);\n if ('kind' in found) return { failure: settled(found) };\n const view = found.authorities.find((held) => held.authority === entry.authority);\n if (view === undefined)\n return { failure: { kind: 'room-not-readable', locator: entry.locator } };\n return { scope: advancedScope(scope, view) };\n }\n\n async function refreshed(entry: SiteTracked, fromRoomVersion: string): Promise<RefreshResult> {\n const from = logPosition(fromRoomVersion);\n if (from === null) return { kind: 'beyond-horizon' };\n const streamed = notifications.advance(entry, from);\n if (streamed !== null) return streamed;\n const found = await enumeration(entry, from);\n if ('kind' in found) return found;\n return refreshFrom(found, entry, fromRoomVersion);\n }\n\n async function acquire(entry: SiteTracked, held: CaughtUp): Promise<HeldModel> {\n if ('failure' in held) return { snapshot: failedModel(held.failure), identity: null };\n const model = await heldModel(\n definitionsOf(held.scope, entry.modelRoot),\n `${authorityRoot(entry.handle)}/${entry.modelRoot}`,\n MODEL_ABSENT,\n );\n acquired.set(entry.authority, { roomVersion: roomVersion(held.scope), model });\n return model;\n }\n\n return {\n async authorize() {\n return {};\n },\n\n async model(_authorization, request): Promise<ModelResult> {\n return models.answer(request);\n },\n\n async discover(): Promise<DiscoverResult> {\n const answer = await transport.read(SITE_DOOR_DISCOVER);\n const classified = classifyDoor(answer.status, answer.body, PRIVATE_LOCATOR);\n if (classified !== null) return discoveryFailure(classified);\n const document = parseSiteDiscovery(answer.body);\n if (document === null) return UNCERTAIN;\n const entries = siteTracked(document);\n tracked.clear();\n for (const entry of entries) tracked.set(entry.locator, entry);\n notifications.track(entries);\n const published = new Set(entries.map((entry) => entry.authority));\n for (const authority of [...acquired.keys()]) {\n if (!published.has(authority)) acquired.delete(authority);\n }\n const fresh = new Map<string, CaughtUp>();\n const current = new Map<string, HeldModel>();\n for (const entry of entries) {\n const kept = acquired.get(entry.authority);\n if (kept !== undefined && kept.roomVersion === roomVersion(entry)) {\n current.set(entry.authority, kept.model);\n continue;\n }\n const held = await caughtUp(entry);\n fresh.set(entry.authority, held);\n current.set(entry.authority, await acquire(entry, held));\n }\n caught = fresh;\n const rooms = entries.map((entry) => {\n const shelved = models.retain(\n modelKey(entry.locator, 'collection'),\n current.get(entry.authority),\n );\n return siteRoom(entry, shelved?.identity ?? null);\n });\n models.keep(entries.map((entry) => entry.locator));\n return { ...mapDiscovery(document, rooms, siteCapabilities()), slots: siteSlots(document) };\n },\n\n async bootstrap(_authorization, request): Promise<BootstrapResult> {\n const entry = tracked.get(request.locator);\n if (entry === undefined) return { kind: 'room-not-readable', locator: request.locator };\n if (request.pageToken !== undefined) return UNCERTAIN;\n const held = caught.get(entry.authority) ?? (await caughtUp(entry));\n if ('failure' in held) return held.failure;\n return bootstrapOf(held.scope, entry);\n },\n\n async refresh(_authorization, request): Promise<RefreshResult> {\n const entry = tracked.get(request.locator);\n if (entry === undefined) return { kind: 'room-not-readable', locator: request.locator };\n if (request.pageToken !== undefined) return UNCERTAIN;\n const result = await refreshed(entry, request.fromRoomVersion);\n if (result.kind === 'beyond-horizon') caught.delete(entry.authority);\n return result;\n },\n\n async mutate() {\n return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {} };\n },\n\n async history() {\n return { kind: 'no-history' };\n },\n\n async action(_authorization, request) {\n if (request.name !== 'submit') {\n return { kind: 'rejected', code: 'action-unimplemented', fields: { name: request.name } };\n }\n if (!transport.online()) return UNCERTAIN;\n return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input), 'submit');\n },\n\n roomVersions: notifications,\n };\n}\n"],"names":["actionOutcome","mapDiscovery","parseSiteDiscovery","siteCapabilities","siteSlots","siteTracked","MODEL_ABSENT","failedModel","heldModel","modelKey","modelShelf","advancedScope","authorityRoot","bootstrapOf","definitionsOf","parseEnumeration","parseSiteBootstrap","refreshFrom","selectionRoots","classifyDoor","discoveryFailure","houseNotifications","PRIVATE_LOCATOR","SITE_DOOR_BOOTSTRAP","SITE_DOOR_DISCOVER","SITE_DOOR_ENUMERATE","SITE_DOOR_SUBMIT","logPosition","presented","roomVersion","UNCERTAIN","kind","siteRoom","tracked","attachedModel","read","name","handle","locator","collectionRoot","operations","sync","write","delete","replica","selection","admission","providerOwnedPaths","settled","refused","createSiteAdapter","transport","notifications","Map","models","acquired","caught","enumeration","entry","from","answer","door","positions","authority","classified","status","body","caughtUp","failure","scope","found","view","authorities","find","held","undefined","refreshed","fromRoomVersion","streamed","advance","acquire","snapshot","identity","model","modelRoot","set","authorize","_authorization","request","discover","document","entries","clear","track","published","Set","map","keys","has","fresh","current","kept","get","rooms","shelved","retain","keep","slots","bootstrap","pageToken","refresh","result","mutate","affected","code","fields","history","action","online","input","roomVersions"],"mappings":"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"}
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { RefreshPage, SelectedRooms
|
|
1
|
+
import type { ConversationStream, RefreshPage, SelectedRooms } from '@agentshouse/mdruntime';
|
|
2
2
|
import type { TrackedAuthority } from './discovery.js';
|
|
3
|
-
import {
|
|
3
|
+
import type { HouseDoor, HouseMode } from './transport.js';
|
|
4
|
+
import { type LogPosition } from './version.js';
|
|
4
5
|
export type HouseNotifications = SelectedRooms & {
|
|
5
6
|
track(authorities: readonly TrackedAuthority[]): void;
|
|
6
|
-
advance(tracked: TrackedAuthority,
|
|
7
|
-
conversations:
|
|
7
|
+
advance(tracked: TrackedAuthority, from: LogPosition): RefreshPage | null;
|
|
8
|
+
conversations: ConversationStream;
|
|
8
9
|
};
|
|
9
|
-
export declare function houseNotifications(transport:
|
|
10
|
+
export declare function houseNotifications(transport: HouseDoor, mode: HouseMode): HouseNotifications;
|
|
10
11
|
//# sourceMappingURL=stream.d.ts.map
|
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,EAEV,WAAW,EAEX,aAAa,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,kBAAkB,EAClB,WAAW,EAEX,aAAa,EACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAsC,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAc7D,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG;IAC/C,KAAK,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACtD,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC;IAC1E,aAAa,EAAE,kBAAkB,CAAC;CACnC,CAAC;AAOF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CA4L5F"}
|
package/dist/stream.js
CHANGED
|
@@ -1,53 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { acceptedMessage, actionOutcome } from './actions.js';
|
|
2
2
|
import { selects } from './read.js';
|
|
3
|
-
import {
|
|
3
|
+
import { roomVersion } from './version.js';
|
|
4
4
|
const HELD_POSITIONS_MAX = 256;
|
|
5
5
|
function position(value) {
|
|
6
6
|
if (!/^(?:0|[1-9][0-9]*)$/.test(value)) return null;
|
|
7
7
|
return BigInt(value);
|
|
8
8
|
}
|
|
9
|
-
function
|
|
10
|
-
if (typeof message !== 'object' || message === null) return null;
|
|
11
|
-
const turn = message.message_id;
|
|
12
|
-
return typeof turn === 'string' ? turn : null;
|
|
13
|
-
}
|
|
14
|
-
export function houseNotifications(transport) {
|
|
9
|
+
export function houseNotifications(transport, mode) {
|
|
15
10
|
const stream = transport.stream;
|
|
16
|
-
const
|
|
11
|
+
const lines = new Map();
|
|
17
12
|
const locators = new Map();
|
|
18
|
-
const authorities = new Map();
|
|
19
13
|
const observers = new Set();
|
|
20
14
|
const conversationObservers = new Set();
|
|
21
|
-
|
|
22
|
-
let selected = [];
|
|
15
|
+
let replicated = [];
|
|
23
16
|
let viewed = [];
|
|
24
17
|
let listening = false;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
named.push({
|
|
31
|
-
kind: 'room',
|
|
32
|
-
room: authority
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
if (authorities.has(PRIVATE_AUTHORITY)) named.push({
|
|
36
|
-
kind: 'private'
|
|
37
|
-
});
|
|
38
|
-
for (const conversation of viewed){
|
|
39
|
-
named.push({
|
|
40
|
-
kind: 'conversation',
|
|
41
|
-
conversation
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
stream.subscribe(named);
|
|
18
|
+
let catching = false;
|
|
19
|
+
function listen() {
|
|
20
|
+
if (listening) return;
|
|
21
|
+
listening = true;
|
|
22
|
+
stream.observe(receive);
|
|
45
23
|
}
|
|
46
24
|
function emitConversation(event) {
|
|
47
|
-
|
|
25
|
+
const delivered = event.kind === 'accepted-message' || event.kind === 'gap' ? replicated : viewed;
|
|
26
|
+
if (!delivered.includes(event.conversation)) return;
|
|
48
27
|
for (const observer of conversationObservers)observer(event);
|
|
49
28
|
}
|
|
50
|
-
async function
|
|
29
|
+
async function summarize(conversation) {
|
|
51
30
|
const viewedAnswer = await transport.door('/door/conversations/view', {
|
|
52
31
|
conversation_id: conversation
|
|
53
32
|
});
|
|
@@ -59,23 +38,30 @@ export function houseNotifications(transport) {
|
|
|
59
38
|
summary: structuredClone('session' in summary.result ? summary.result.session : null)
|
|
60
39
|
});
|
|
61
40
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
41
|
+
}
|
|
42
|
+
function reopened() {
|
|
43
|
+
for (const conversation of replicated)emitConversation({
|
|
44
|
+
kind: 'gap',
|
|
45
|
+
conversation
|
|
46
|
+
});
|
|
47
|
+
for (const conversation of viewed)void summarize(conversation);
|
|
48
|
+
}
|
|
49
|
+
function announce(authority, at) {
|
|
50
|
+
const version = roomVersion(at);
|
|
51
|
+
for (const locator of locators.get(authority) ?? []){
|
|
52
|
+
for (const observer of observers)observer({
|
|
53
|
+
locator,
|
|
54
|
+
roomVersion: version
|
|
76
55
|
});
|
|
77
56
|
}
|
|
78
57
|
}
|
|
58
|
+
function interrupt(authority) {
|
|
59
|
+
const line = lines.get(authority);
|
|
60
|
+
if (line !== undefined) lines.set(authority, {
|
|
61
|
+
logEpoch: line.logEpoch,
|
|
62
|
+
frames: []
|
|
63
|
+
});
|
|
64
|
+
}
|
|
79
65
|
function receive(frame) {
|
|
80
66
|
if (frame.type === 'draft') {
|
|
81
67
|
emitConversation({
|
|
@@ -87,15 +73,12 @@ export function houseNotifications(transport) {
|
|
|
87
73
|
return;
|
|
88
74
|
}
|
|
89
75
|
if (frame.type === 'message') {
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
76
|
+
const message = acceptedMessage(frame.message);
|
|
77
|
+
if (message === null) return;
|
|
92
78
|
emitConversation({
|
|
93
79
|
kind: 'accepted-message',
|
|
94
80
|
conversation: frame.conversation_id,
|
|
95
|
-
message
|
|
96
|
-
turn,
|
|
97
|
-
message: structuredClone(frame.message)
|
|
98
|
-
}
|
|
81
|
+
message
|
|
99
82
|
});
|
|
100
83
|
return;
|
|
101
84
|
}
|
|
@@ -107,61 +90,60 @@ export function houseNotifications(transport) {
|
|
|
107
90
|
});
|
|
108
91
|
return;
|
|
109
92
|
}
|
|
110
|
-
if (frame.type
|
|
111
|
-
const reconnect = subscribedConversations.has(frame.authority);
|
|
112
|
-
subscribedConversations.add(frame.authority);
|
|
113
|
-
void catchUp(frame.authority, reconnect);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (frame.type !== 'entries') {
|
|
117
|
-
held.delete(frame.authority);
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
93
|
+
if (frame.type !== 'entries') return;
|
|
120
94
|
const at = position(frame.position);
|
|
121
95
|
if (at === null) {
|
|
122
|
-
|
|
96
|
+
interrupt(frame.authority);
|
|
123
97
|
return;
|
|
124
98
|
}
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
99
|
+
const line = lines.get(frame.authority);
|
|
100
|
+
if (line?.logEpoch === frame.log_epoch) {
|
|
101
|
+
const last = line.frames.at(-1);
|
|
102
|
+
const continued = last !== undefined && last.position + 1n === at;
|
|
103
|
+
const next = continued ? [
|
|
104
|
+
...line.frames,
|
|
105
|
+
{
|
|
106
|
+
position: at,
|
|
107
|
+
entries: frame.entries
|
|
108
|
+
}
|
|
109
|
+
] : [
|
|
110
|
+
{
|
|
111
|
+
position: at,
|
|
112
|
+
entries: frame.entries
|
|
113
|
+
}
|
|
114
|
+
];
|
|
115
|
+
lines.set(frame.authority, {
|
|
116
|
+
logEpoch: line.logEpoch,
|
|
117
|
+
frames: next.length > HELD_POSITIONS_MAX ? [] : next
|
|
118
|
+
});
|
|
119
|
+
} else {
|
|
120
|
+
interrupt(frame.authority);
|
|
121
|
+
}
|
|
122
|
+
announce(frame.authority, {
|
|
123
|
+
position: frame.position,
|
|
124
|
+
logEpoch: frame.log_epoch
|
|
146
125
|
});
|
|
147
126
|
}
|
|
148
127
|
return {
|
|
149
128
|
conversations: {
|
|
129
|
+
replicate (next) {
|
|
130
|
+
replicated = [
|
|
131
|
+
...next
|
|
132
|
+
];
|
|
133
|
+
},
|
|
150
134
|
view (next) {
|
|
151
|
-
const
|
|
152
|
-
for (const conversation of subscribedConversations){
|
|
153
|
-
if (!open.has(conversation)) subscribedConversations.delete(conversation);
|
|
154
|
-
}
|
|
135
|
+
const entering = next.filter((conversation)=>!viewed.includes(conversation));
|
|
155
136
|
viewed = [
|
|
156
137
|
...next
|
|
157
138
|
];
|
|
158
|
-
|
|
139
|
+
for (const conversation of entering)void summarize(conversation);
|
|
159
140
|
},
|
|
160
141
|
observe (notify) {
|
|
161
142
|
conversationObservers.add(notify);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
143
|
+
listen();
|
|
144
|
+
if (!catching) {
|
|
145
|
+
catching = true;
|
|
146
|
+
stream.opened(reopened);
|
|
165
147
|
}
|
|
166
148
|
return ()=>{
|
|
167
149
|
conversationObservers.delete(notify);
|
|
@@ -170,38 +152,37 @@ export function houseNotifications(transport) {
|
|
|
170
152
|
},
|
|
171
153
|
track (entries) {
|
|
172
154
|
locators.clear();
|
|
173
|
-
authorities.clear();
|
|
174
155
|
for (const entry of entries){
|
|
175
|
-
locators.set(entry.authority,
|
|
176
|
-
|
|
156
|
+
locators.set(entry.authority, [
|
|
157
|
+
...locators.get(entry.authority) ?? [],
|
|
158
|
+
entry.locator
|
|
159
|
+
]);
|
|
160
|
+
if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
|
|
161
|
+
lines.set(entry.authority, {
|
|
162
|
+
logEpoch: entry.logEpoch,
|
|
163
|
+
frames: []
|
|
164
|
+
});
|
|
165
|
+
}
|
|
177
166
|
}
|
|
178
|
-
for (const authority of
|
|
179
|
-
if (!locators.has(authority))
|
|
167
|
+
for (const authority of lines.keys()){
|
|
168
|
+
if (!locators.has(authority)) lines.delete(authority);
|
|
180
169
|
}
|
|
181
170
|
},
|
|
182
|
-
select (
|
|
183
|
-
selected = [
|
|
184
|
-
...named
|
|
185
|
-
];
|
|
186
|
-
subscribe();
|
|
187
|
-
},
|
|
171
|
+
select () {},
|
|
188
172
|
observe (notify) {
|
|
189
173
|
observers.add(notify);
|
|
190
|
-
|
|
191
|
-
listening = true;
|
|
192
|
-
stream.observe(receive);
|
|
193
|
-
}
|
|
174
|
+
listen();
|
|
194
175
|
return ()=>{
|
|
195
176
|
observers.delete(notify);
|
|
196
177
|
};
|
|
197
178
|
},
|
|
198
|
-
advance (tracked,
|
|
199
|
-
const
|
|
200
|
-
const
|
|
201
|
-
if (
|
|
202
|
-
const at =
|
|
179
|
+
advance (tracked, from) {
|
|
180
|
+
const line = lines.get(tracked.authority);
|
|
181
|
+
const start = position(from.position);
|
|
182
|
+
if (line === undefined || start === null || line.logEpoch !== from.logEpoch) return null;
|
|
183
|
+
const at = line.frames.findIndex((frame)=>frame.position === start + 1n);
|
|
203
184
|
if (at === -1) return null;
|
|
204
|
-
const pending =
|
|
185
|
+
const pending = line.frames.slice(at);
|
|
205
186
|
const documents = {};
|
|
206
187
|
const revisions = {};
|
|
207
188
|
const removals = [];
|
|
@@ -214,19 +195,26 @@ export function houseNotifications(transport) {
|
|
|
214
195
|
if (!removals.includes(entry.path)) removals.push(entry.path);
|
|
215
196
|
continue;
|
|
216
197
|
}
|
|
217
|
-
if (entry.text === undefined
|
|
198
|
+
if (entry.text === undefined) return null;
|
|
199
|
+
if (mode === 'credential' && entry.revision === undefined) return null;
|
|
218
200
|
documents[entry.path] = entry.text;
|
|
219
|
-
revisions[entry.path] = entry.revision;
|
|
201
|
+
if (entry.revision !== undefined) revisions[entry.path] = entry.revision;
|
|
220
202
|
const removed = removals.indexOf(entry.path);
|
|
221
203
|
if (removed !== -1) removals.splice(removed, 1);
|
|
222
204
|
}
|
|
223
205
|
}
|
|
224
206
|
const last = pending.at(-1);
|
|
225
207
|
if (last === undefined) return null;
|
|
226
|
-
|
|
208
|
+
lines.set(tracked.authority, {
|
|
209
|
+
logEpoch: line.logEpoch,
|
|
210
|
+
frames: pending
|
|
211
|
+
});
|
|
227
212
|
return {
|
|
228
213
|
kind: 'net-advancement',
|
|
229
|
-
roomVersion:
|
|
214
|
+
roomVersion: roomVersion({
|
|
215
|
+
position: last.position.toString(),
|
|
216
|
+
logEpoch: line.logEpoch
|
|
217
|
+
}),
|
|
230
218
|
documents,
|
|
231
219
|
revisions,
|
|
232
220
|
binaryTargets: [],
|