@agentshouse/mdruntime-adapter 0.1.0-cc7fa1e066844 → 0.1.0-cf22c8563f9f4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/site.js CHANGED
@@ -1,43 +1,34 @@
1
1
  import { actionOutcome } from './actions.js';
2
2
  import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteTracked, } from './discovery.js';
3
- import { MODEL_ABSENT, failedModel, heldModel, modelKey, modelShelf, } from './model.js';
4
- import { advancedScope, bootstrapOf, parseEnumeration, parseSiteBootstrap, refreshFrom, schemaOf, schemaPath, viewOf, } from './read.js';
5
- import { classifyDoor, discoveryFailure, doorRefusal } from './refusal.js';
3
+ import { scopeModels, streamedModels, viewModels } from './model.js';
4
+ import { advancedScope, bootstrapOf, parseEnumeration, parseSiteBootstrap, refreshFrom, viewOf, } from './read.js';
5
+ import { classifyDoor, classifyRead, discoveryFailure } from './refusal.js';
6
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, reachedVersion, roomVersion, } from './version.js';
7
+ import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT, } from './transport.js';
8
+ import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
9
9
  const UNCERTAIN = { kind: 'transport-uncertainty' };
10
- function siteRoom(tracked, attachedModel) {
10
+ function siteRoom(tracked) {
11
11
  return {
12
12
  name: tracked.handle,
13
13
  locator: tracked.locator,
14
+ handle: tracked.handle,
14
15
  roomVersion: roomVersion(tracked),
15
16
  operations: { read: [''], sync: [''], write: [], delete: [] },
16
17
  replica: { selection: tracked.locator, admission: 'admitted' },
17
- attachedModel,
18
18
  providerOwnedPaths: [],
19
19
  };
20
20
  }
21
21
  function settled(refused) {
22
- return refused.kind === 'beyond-horizon' || refused.kind === 'retryable-refusal'
23
- ? UNCERTAIN
24
- : refused;
22
+ return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;
25
23
  }
26
24
  export function createSiteAdapter(transport) {
27
25
  const notifications = houseNotifications(transport, 'site');
28
26
  const tracked = new Map();
29
- const models = modelShelf();
30
- const acquired = new Map();
31
- let caught = new Map();
32
27
  async function enumeration(entry, from) {
33
28
  const answer = await transport.door(SITE_DOOR_ENUMERATE, {
34
29
  positions: [presented(entry.authority, from)],
35
30
  });
36
- const behind = doorRefusal(answer.body);
37
- if (behind?.code === 'replica_behind' && behind.retryable) {
38
- return { kind: 'retryable-refusal', code: behind.code, fields: behind.fields };
39
- }
40
- const classified = classifyDoor(answer.status, answer.body, entry.locator);
31
+ const classified = classifyRead(answer.status, answer.body, entry.locator);
41
32
  if (classified !== null)
42
33
  return classified;
43
34
  return parseEnumeration(answer.body, 'site') ?? UNCERTAIN;
@@ -46,7 +37,7 @@ export function createSiteAdapter(transport) {
46
37
  const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}`);
47
38
  const classified = classifyDoor(answer.status, answer.body, entry.locator);
48
39
  if (classified !== null)
49
- return { failure: settled(classified) };
40
+ return { failure: classified };
50
41
  const scope = parseSiteBootstrap(answer.body);
51
42
  if (scope === null)
52
43
  return { failure: UNCERTAIN };
@@ -65,36 +56,32 @@ export function createSiteAdapter(transport) {
65
56
  if (from === null)
66
57
  return { kind: 'beyond-horizon' };
67
58
  const streamed = notifications.advance(entry, from);
68
- if (streamed !== null)
69
- return streamed.page;
59
+ if (streamed !== null) {
60
+ const models = await streamedModels(streamed.schemas, entry, 'site');
61
+ return models === undefined ? streamed.page : { ...streamed.page, models };
62
+ }
70
63
  const found = await enumeration(entry, from);
71
64
  if ('kind' in found)
72
65
  return found;
73
66
  const view = viewOf(found, entry);
74
67
  if (view === undefined)
75
68
  return { kind: 'room-not-readable', locator: entry.locator };
76
- notifications.hold(entry.authority, view);
77
- return refreshFrom(view, fromRoomVersion);
78
- }
79
- async function acquire(entry, held) {
80
- if ('failure' in held)
81
- return { snapshot: failedModel(held.failure), identity: null };
82
- const model = await heldModel(schemaOf(held.scope, entry.schema), schemaPath(entry.handle, entry.schema), MODEL_ABSENT);
83
- acquired.set(entry.authority, { roomVersion: roomVersion(held.scope), model });
84
- return model;
69
+ notifications.reach(entry.authority, view);
70
+ const answer = refreshFrom(view, fromRoomVersion);
71
+ if (answer.kind !== 'net-advancement')
72
+ return answer;
73
+ const models = await viewModels(view, entry);
74
+ return models === undefined ? answer : { ...answer, models };
85
75
  }
86
76
  return {
87
77
  async authorize() {
88
78
  return {};
89
79
  },
90
- async model(_authorization, request) {
91
- return models.answer(request);
92
- },
93
80
  async discover() {
94
81
  const answer = await transport.read(SITE_DOOR_DISCOVER);
95
- const classified = classifyDoor(answer.status, answer.body, PRIVATE_LOCATOR);
96
- if (classified !== null)
97
- return discoveryFailure(classified);
82
+ const failed = discoveryFailure(answer.status, answer.body);
83
+ if (failed !== null)
84
+ return failed;
98
85
  const document = parseSiteDiscovery(answer.body);
99
86
  if (document === null)
100
87
  return UNCERTAIN;
@@ -103,30 +90,7 @@ export function createSiteAdapter(transport) {
103
90
  for (const entry of entries)
104
91
  tracked.set(entry.locator, entry);
105
92
  notifications.track(entries);
106
- const published = new Set(entries.map((entry) => entry.authority));
107
- for (const authority of [...acquired.keys()]) {
108
- if (!published.has(authority))
109
- acquired.delete(authority);
110
- }
111
- const fresh = new Map();
112
- const current = new Map();
113
- for (const entry of entries) {
114
- const kept = acquired.get(entry.authority);
115
- if (kept !== undefined && kept.roomVersion === roomVersion(entry)) {
116
- current.set(entry.authority, kept.model);
117
- continue;
118
- }
119
- const held = await caughtUp(entry);
120
- fresh.set(entry.authority, held);
121
- current.set(entry.authority, await acquire(entry, held));
122
- }
123
- caught = fresh;
124
- const rooms = entries.map((entry) => {
125
- const shelved = models.retain(modelKey(entry.locator, 'collection'), current.get(entry.authority));
126
- return siteRoom(entry, shelved?.identity ?? null);
127
- });
128
- models.keep(entries.map((entry) => entry.locator));
129
- return mapDiscovery(document, rooms, siteCapabilities());
93
+ return mapDiscovery(document, entries.map(siteRoom), siteCapabilities());
130
94
  },
131
95
  async bootstrap(_authorization, request) {
132
96
  const entry = tracked.get(request.locator);
@@ -134,11 +98,12 @@ export function createSiteAdapter(transport) {
134
98
  return { kind: 'room-not-readable', locator: request.locator };
135
99
  if (request.pageToken !== undefined)
136
100
  return UNCERTAIN;
137
- const held = caught.get(entry.authority) ?? (await caughtUp(entry));
101
+ const held = await caughtUp(entry);
138
102
  if ('failure' in held)
139
103
  return held.failure;
140
- notifications.hold(entry.authority, held.scope);
141
- return bootstrapOf(held.scope);
104
+ notifications.reach(entry.authority, held.scope);
105
+ const models = await scopeModels(held.scope, entry);
106
+ return { ...bootstrapOf(held.scope), ...(models === undefined ? {} : { models }) };
142
107
  },
143
108
  async refresh(_authorization, request) {
144
109
  const entry = tracked.get(request.locator);
@@ -146,20 +111,7 @@ export function createSiteAdapter(transport) {
146
111
  return { kind: 'room-not-readable', locator: request.locator };
147
112
  if (request.pageToken !== undefined)
148
113
  return UNCERTAIN;
149
- const result = await refreshed(entry, request.fromRoomVersion);
150
- if (result.kind === 'beyond-horizon')
151
- caught.delete(entry.authority);
152
- const answered = result.kind === 'net-advancement'
153
- ? result.roomVersion
154
- : result.kind === 'still-current'
155
- ? request.fromRoomVersion
156
- : null;
157
- if (request.minPosition !== undefined &&
158
- answered !== null &&
159
- !reachedVersion(answered, request.minPosition, entry.logEpoch)) {
160
- return { kind: 'retryable-refusal', code: 'replica_behind', fields: {} };
161
- }
162
- return result;
114
+ return refreshed(entry, request.fromRoomVersion);
163
115
  },
164
116
  async mutate() {
165
117
  return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {} };
@@ -170,6 +122,9 @@ export function createSiteAdapter(transport) {
170
122
  reached(locator, version, target) {
171
123
  return reachedVersion(version, target, tracked.get(locator)?.logEpoch);
172
124
  },
125
+ follows(_locator, version, next) {
126
+ return followsVersion(version, next);
127
+ },
173
128
  async action(_authorization, request) {
174
129
  if (request.name !== 'submit') {
175
130
  return { kind: 'rejected', code: 'action-unimplemented', fields: { name: request.name } };
@@ -178,7 +133,19 @@ export function createSiteAdapter(transport) {
178
133
  return UNCERTAIN;
179
134
  return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input), 'submit');
180
135
  },
181
- roomVersions: notifications,
136
+ roomStream: {
137
+ hold(rooms) {
138
+ notifications.send(rooms.flatMap((room) => {
139
+ const entry = tracked.get(room.locator);
140
+ const at = logPosition(room.roomVersion);
141
+ if (entry === undefined || at === null)
142
+ return [];
143
+ notifications.reach(entry.authority, at);
144
+ return [presented(entry.authority, at)];
145
+ }));
146
+ },
147
+ observe: notifications.observe,
148
+ },
182
149
  serviceMode: notifications.serviceMode,
183
150
  };
184
151
  }
package/dist/stream.d.ts CHANGED
@@ -1,15 +1,19 @@
1
- import type { ConversationStream, RefreshPage, SelectedRooms, ServiceModeSignal } from '@agentshouse/mdruntime';
1
+ import type { ConversationStream, RefreshPage, RoomStreamEvent, ServiceModeSignal } from '@agentshouse/mdruntime';
2
2
  import type { TrackedAuthority } from './discovery.js';
3
- import type { HouseDoor, HouseMode, HouseStreamEntry } from './transport.js';
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
8
  entries: readonly HouseStreamEntry[];
9
+ schemas: ReadonlyMap<string, HouseStreamEntry>;
9
10
  };
10
- export type HouseNotifications = SelectedRooms & {
11
+ export type HouseNotifications = {
12
+ runtime: string;
13
+ observe(notify: (event: RoomStreamEvent) => void): () => void;
14
+ send(rooms: readonly HouseHeldRoom[]): void;
11
15
  track(authorities: readonly TrackedAuthority[]): void;
12
- hold(authority: string, at: LogPosition): void;
16
+ reach(authority: string, at: LogPosition): void;
13
17
  advance(tracked: TrackedAuthority, from: LogPosition, holds?: HeldRevision): StreamedAdvancement | null;
14
18
  conversations: ConversationStream;
15
19
  serviceMode: ServiceModeSignal;
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,kBAAkB,EAClB,WAAW,EAEX,aAAa,EAEb,iBAAiB,EAElB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAoB,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAgB7D,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,SAAS,gBAAgB,EAAE,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG;IAC/C,KAAK,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACtD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/C,OAAO,CACL,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,KAAK,CAAC,EAAE,YAAY,GACnB,mBAAmB,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,kBAAkB,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAYF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CA2P5F"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,kBAAkB,EAElB,WAAW,EACX,eAAe,EAEf,iBAAiB,EAElB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EAEb,SAAS,EAET,gBAAgB,EAEjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAgB7D,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,SAAS,gBAAgB,EAAE,CAAC;IACrC,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,GAAG,MAAM,IAAI,CAAC;IAC9D,IAAI,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,OAAO,CACL,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,KAAK,CAAC,EAAE,YAAY,GACnB,mBAAmB,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,kBAAkB,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAuBF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CAoS5F"}
package/dist/stream.js CHANGED
@@ -6,6 +6,16 @@ function turnOperation(frame) {
6
6
  const { type: _type, conversation_id: _conversation, turn_id: _turn, ...operation } = frame;
7
7
  return structuredClone(operation);
8
8
  }
9
+ function listedConversation(listed) {
10
+ return {
11
+ conversation: listed.conversation_id,
12
+ agent: listed.agent_id,
13
+ name: listed.name,
14
+ created: listed.created_at,
15
+ finished: listed.finished_at,
16
+ outcome: listed.outcome,
17
+ };
18
+ }
9
19
  function position(value) {
10
20
  if (!/^(?:0|[1-9][0-9]*)$/.test(value))
11
21
  return null;
@@ -15,31 +25,35 @@ export function houseNotifications(transport, mode) {
15
25
  const stream = transport.stream;
16
26
  const lines = new Map();
17
27
  const locators = new Map();
18
- const schemas = new Map();
19
28
  const observers = new Set();
20
29
  const conversationObservers = new Set();
21
30
  const modeObservers = new Set();
22
31
  let replicated = [];
23
32
  const live = new Set();
24
- let listening = false;
25
- let catching = false;
26
- function listen() {
27
- if (listening)
28
- return;
29
- listening = true;
30
- stream.observe(receive);
33
+ let opening = null;
34
+ const runtime = crypto.randomUUID();
35
+ function emit(event) {
36
+ for (const observer of observers)
37
+ observer(event);
31
38
  }
32
39
  function emitConversation(event) {
33
- if (event.kind !== 'gap' && event.kind !== 'accepted-message')
40
+ if (event.kind === 'turn' ||
41
+ event.kind === 'questions' ||
42
+ event.kind === 'process' ||
43
+ event.kind === 'commands' ||
44
+ event.kind === 'options') {
34
45
  live.add(event.conversation);
46
+ }
35
47
  for (const observer of conversationObservers)
36
48
  observer(event);
37
49
  }
38
- function reopened() {
50
+ function reopened(next) {
51
+ opening = next;
39
52
  const gapped = new Set([...replicated, ...live]);
40
53
  live.clear();
41
54
  for (const conversation of gapped)
42
55
  emitConversation({ kind: 'gap', conversation });
56
+ emit({ kind: 'opened' });
43
57
  }
44
58
  function converse(frame) {
45
59
  const conversation = frame.conversation_id;
@@ -85,14 +99,10 @@ export function houseNotifications(transport, mode) {
85
99
  return;
86
100
  emitConversation({ kind: 'accepted-message', conversation, message });
87
101
  }
88
- function announce(authority, at, modelChanged) {
102
+ function announce(authority, at) {
89
103
  const version = roomVersion(at);
90
104
  for (const locator of locators.get(authority) ?? []) {
91
- for (const observer of observers) {
92
- observer(modelChanged
93
- ? { locator, roomVersion: version, modelChanged: true }
94
- : { locator, roomVersion: version });
95
- }
105
+ emit({ kind: 'room-version', locator, roomVersion: version });
96
106
  }
97
107
  }
98
108
  function interrupt(authority) {
@@ -109,6 +119,25 @@ export function houseNotifications(transport, mode) {
109
119
  observer(mode);
110
120
  return;
111
121
  }
122
+ if (frame.type === 'opening') {
123
+ emit({
124
+ kind: 'opening',
125
+ expired: frame.expired.flatMap((authority) => locators.get(authority) ?? []),
126
+ });
127
+ return;
128
+ }
129
+ if (frame.type === 'conversations') {
130
+ emitConversation({ kind: 'list', entries: frame.conversations.map(listedConversation) });
131
+ return;
132
+ }
133
+ if (frame.type === 'conversation') {
134
+ emitConversation({ kind: 'listed', entry: listedConversation(frame.conversation) });
135
+ return;
136
+ }
137
+ if (frame.type === 'conversation_deleted') {
138
+ emitConversation({ kind: 'unlisted', conversation: frame.conversation_id });
139
+ return;
140
+ }
112
141
  if (frame.type === 'turn' ||
113
142
  frame.type === 'process' ||
114
143
  frame.type === 'commands' ||
@@ -140,14 +169,19 @@ export function houseNotifications(transport, mode) {
140
169
  else {
141
170
  interrupt(frame.authority);
142
171
  }
143
- const addresses = schemas.get(frame.authority) ?? [];
144
- announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch }, frame.entries.some((entry) => addresses.includes(entry.path)));
172
+ announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });
145
173
  }
174
+ stream.observe(receive);
175
+ stream.opened(reopened);
176
+ stream.closed((revoked) => {
177
+ opening = null;
178
+ emit({ kind: 'closed', revoked });
179
+ });
146
180
  return {
181
+ runtime,
147
182
  serviceMode: {
148
183
  observe(notify) {
149
184
  modeObservers.add(notify);
150
- listen();
151
185
  return () => {
152
186
  modeObservers.delete(notify);
153
187
  };
@@ -159,22 +193,39 @@ export function houseNotifications(transport, mode) {
159
193
  },
160
194
  observe(notify) {
161
195
  conversationObservers.add(notify);
162
- listen();
163
- if (!catching) {
164
- catching = true;
165
- stream.opened(reopened);
166
- }
167
196
  return () => {
168
197
  conversationObservers.delete(notify);
169
198
  };
170
199
  },
171
200
  },
201
+ observe(notify) {
202
+ observers.add(notify);
203
+ if (opening !== null) {
204
+ queueMicrotask(() => {
205
+ if (observers.has(notify))
206
+ notify({ kind: 'opened' });
207
+ });
208
+ }
209
+ return () => {
210
+ observers.delete(notify);
211
+ };
212
+ },
213
+ send(rooms) {
214
+ for (const room of rooms) {
215
+ const line = lines.get(room.authority);
216
+ const held = position(room.position);
217
+ if (line === undefined || held === null || line.logEpoch !== room.log_epoch)
218
+ continue;
219
+ lines.set(room.authority, { ...line, frames: [], held });
220
+ }
221
+ const current = opening;
222
+ opening = null;
223
+ current?.hold(rooms, runtime);
224
+ },
172
225
  track(entries) {
173
226
  locators.clear();
174
- schemas.clear();
175
227
  for (const entry of entries) {
176
228
  locators.set(entry.authority, [...(locators.get(entry.authority) ?? []), entry.locator]);
177
- schemas.set(entry.authority, entry.schemas);
178
229
  if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
179
230
  lines.set(entry.authority, { logEpoch: entry.logEpoch, frames: [], held: null });
180
231
  }
@@ -184,20 +235,18 @@ export function houseNotifications(transport, mode) {
184
235
  lines.delete(authority);
185
236
  }
186
237
  },
187
- select() { },
188
- observe(notify) {
189
- observers.add(notify);
190
- listen();
191
- return () => {
192
- observers.delete(notify);
193
- };
194
- },
195
- hold(authority, at) {
238
+ reach(authority, at) {
196
239
  const line = lines.get(authority);
197
240
  const held = position(at.position);
198
241
  if (line === undefined || held === null || line.logEpoch !== at.logEpoch)
199
242
  return;
200
- lines.set(authority, { ...line, held });
243
+ if (line.held !== null && held <= line.held)
244
+ return;
245
+ lines.set(authority, {
246
+ ...line,
247
+ frames: line.frames.filter((frame) => frame.position > held),
248
+ held,
249
+ });
201
250
  },
202
251
  advance(tracked, from, holds) {
203
252
  const line = lines.get(tracked.authority);
@@ -213,6 +262,7 @@ export function houseNotifications(transport, mode) {
213
262
  const changes = {};
214
263
  const removals = [];
215
264
  const applied = [];
265
+ const schemas = new Map();
216
266
  const forget = (path) => {
217
267
  delete documents[path];
218
268
  delete revisions[path];
@@ -224,13 +274,14 @@ export function houseNotifications(transport, mode) {
224
274
  for (const frame of pending) {
225
275
  for (const entry of frame.entries) {
226
276
  if (entry.kind === 'edited' &&
227
- entry.text === undefined &&
228
277
  entry.revision !== undefined &&
229
278
  holds?.(entry.path, entry.revision) === true) {
230
279
  forget(entry.path);
231
280
  continue;
232
281
  }
233
282
  applied.push(entry);
283
+ if (tracked.schemas.includes(entry.path))
284
+ schemas.set(entry.path, entry);
234
285
  if (entry.kind === 'removed') {
235
286
  forget(entry.path);
236
287
  removals.push(entry.path);
@@ -264,6 +315,7 @@ export function houseNotifications(transport, mode) {
264
315
  removals: removals.sort(),
265
316
  },
266
317
  entries: applied,
318
+ schemas,
267
319
  };
268
320
  },
269
321
  };
@@ -9,7 +9,6 @@ export declare const SITE_DOOR_DISCOVER = "/_house/door/discover";
9
9
  export declare const SITE_DOOR_BOOTSTRAP = "/_house/door/bootstrap/";
10
10
  export declare const SITE_DOOR_ENUMERATE = "/_house/door/enumerate";
11
11
  export declare const SITE_DOOR_SUBMIT = "/_house/door/submit";
12
- export declare const PRIVATE_LOCATOR = "private";
13
12
  export type HouseMode = 'credential' | 'site';
14
13
  export type HouseDoorAnswer = {
15
14
  status: number;
@@ -30,6 +29,7 @@ export type HouseStreamEntry = {
30
29
  path: string;
31
30
  kind: 'edited' | 'removed';
32
31
  revision?: string;
32
+ sha256?: string;
33
33
  text?: string;
34
34
  author?: {
35
35
  user: string;
@@ -43,6 +43,14 @@ export type HouseStreamEntry = {
43
43
  type LiveFact<K extends ConversationEvent['kind']> = Extract<ConversationEvent, {
44
44
  kind: K;
45
45
  }>;
46
+ export type HouseListedConversation = {
47
+ conversation_id: string;
48
+ agent_id: string;
49
+ name: string;
50
+ created_at: string;
51
+ finished_at: string | null;
52
+ outcome: string | null;
53
+ };
46
54
  export type HouseStreamFrame = {
47
55
  type: 'entries';
48
56
  authority: string;
@@ -50,6 +58,9 @@ export type HouseStreamFrame = {
50
58
  position: string;
51
59
  log_epoch: string;
52
60
  entries: readonly HouseStreamEntry[];
61
+ } | {
62
+ type: 'opening';
63
+ expired: readonly string[];
53
64
  } | ({
54
65
  type: 'turn';
55
66
  conversation_id: string;
@@ -74,13 +85,31 @@ export type HouseStreamFrame = {
74
85
  type: 'options';
75
86
  conversation_id: string;
76
87
  options: LiveFact<'options'>['options'];
88
+ } | {
89
+ type: 'conversations';
90
+ conversations: readonly HouseListedConversation[];
91
+ } | {
92
+ type: 'conversation';
93
+ conversation: HouseListedConversation;
94
+ } | {
95
+ type: 'conversation_deleted';
96
+ conversation_id: string;
77
97
  } | {
78
98
  type: 'signal';
79
99
  service_mode: string;
80
100
  };
101
+ export type HouseHeldRoom = {
102
+ authority: string;
103
+ position: string;
104
+ log_epoch: string;
105
+ };
106
+ export type HouseOpening = {
107
+ hold(rooms: readonly HouseHeldRoom[], runtime: string): void;
108
+ };
81
109
  export type HouseStream = {
82
110
  observe(receive: (frame: HouseStreamFrame) => void): () => void;
83
- opened(notify: () => void): () => void;
111
+ opened(notify: (opening: HouseOpening) => void): () => void;
112
+ closed(notify: (revoked: boolean) => void): () => void;
84
113
  };
85
114
  export type HouseDoor = {
86
115
  door(route: string, body: unknown): Promise<HouseDoorAnswer>;
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE/E,eAAO,MAAM,aAAa,mBAAmB,CAAC;AAE9C,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,eAAO,MAAM,UAAU,gBAAgB,CAAC;AAExC,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D,eAAO,MAAM,mBAAmB,4BAA4B,CAAC;AAE7D,eAAO,MAAM,mBAAmB,2BAA2B,CAAC;AAE5D,eAAO,MAAM,gBAAgB,wBAAwB,CAAC;AAEtD,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAE9C,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,mBAAmB,GACnB,uBAAuB,GACvB,8BAA8B,GAC9B,iBAAiB,GACjB,mBAAmB,CAAC;AAExB,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAE9D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,QAAQ,CAAC,CAAC,SAAS,iBAAiB,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,iBAAiB,EAAE;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,CAAC;AAE7F,MAAM,MAAM,uBAAuB,GAAG;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACtC,GACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC/C,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAAC,GAC5E;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,GACnF;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAA;CAAE,GACrF;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,aAAa,EAAE,SAAS,uBAAuB,EAAE,CAAA;CAAE,GAC5E;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,uBAAuB,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9D,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAChE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5D,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC7D,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG;IACvC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAChE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG;IAC3C,MAAM,IAAI,OAAO,CAAC;IAClB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC/C,CAAC"}
package/dist/transport.js CHANGED
@@ -8,4 +8,3 @@ export const SITE_DOOR_DISCOVER = '/_house/door/discover';
8
8
  export const SITE_DOOR_BOOTSTRAP = '/_house/door/bootstrap/';
9
9
  export const SITE_DOOR_ENUMERATE = '/_house/door/enumerate';
10
10
  export const SITE_DOOR_SUBMIT = '/_house/door/submit';
11
- export const PRIVATE_LOCATOR = 'private';
package/dist/version.d.ts CHANGED
@@ -12,4 +12,5 @@ export declare function logPosition(version: string): LogPosition | null;
12
12
  export declare function readPosition(held: Readonly<Record<string, unknown>>): LogPosition | null;
13
13
  export declare function presented(authority: string, at: LogPosition): PresentedPosition;
14
14
  export declare function reachedVersion(roomVersion: string, target: string, currentEpoch: string | undefined): boolean;
15
+ export declare function followsVersion(roomVersion: string, next: string): boolean;
15
16
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAEnD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,WAAW,GAAG,IAAI,CAKxF;AAED,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,iBAAiB,CAE/E;AAID,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,OAAO,CAQT"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAEnD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,WAAW,GAAG,IAAI,CAKxF;AAED,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,iBAAiB,CAE/E;AAID,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,OAAO,CAQT;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAMzE"}
package/dist/version.js CHANGED
@@ -32,3 +32,12 @@ export function reachedVersion(roomVersion, target, currentEpoch) {
32
32
  return BigInt(held.position) >= BigInt(wanted.position);
33
33
  return held.logEpoch === currentEpoch;
34
34
  }
35
+ export function followsVersion(roomVersion, next) {
36
+ const held = logPosition(roomVersion);
37
+ const following = logPosition(next);
38
+ if (held === null || following === null || held.logEpoch !== following.logEpoch)
39
+ return false;
40
+ if (!DECIMAL.test(held.position) || !DECIMAL.test(following.position))
41
+ return false;
42
+ return BigInt(following.position) === BigInt(held.position) + 1n;
43
+ }
package/dist/write.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ChangeBatch, HistoryResult, MutationResult } from '@agentshouse/mdruntime';
1
+ import type { ChangeBatch, HistoryResult, MutationResult, RoomAttachment } from '@agentshouse/mdruntime';
2
2
  import type { HouseBounds } from './discovery.js';
3
3
  export type HouseOperation = Readonly<Record<string, unknown>>;
4
4
  export type ChangeMapping = {
@@ -21,7 +21,14 @@ export declare function deltaBody(changes: readonly HouseOperation[]): string;
21
21
  export declare function deltaBytes(delta: string): number;
22
22
  export declare function uploadable(inline: Readonly<Record<string, unknown>>, bytes: number, bounds: Pick<HouseBounds, 'max_inline_body_bytes' | 'max_upload_bytes'>): boolean;
23
23
  export declare function deltaDigest(delta: string): Promise<string>;
24
- export declare function mutationOutcome(status: number, body: unknown, locator: string, handle: string): MutationResult;
24
+ export type SubmittedOutcome = Exclude<MutationResult, {
25
+ kind: 'accepted';
26
+ }> | (Extract<MutationResult, {
27
+ kind: 'accepted';
28
+ }> & {
29
+ originals: readonly RoomAttachment[];
30
+ });
31
+ export declare function mutationOutcome(status: number, body: unknown, locator: string, handle: string): SubmittedOutcome;
25
32
  export declare function rejectedMapping(mapping: Extract<ChangeMapping, {
26
33
  kind: 'unmapped';
27
34
  }>): {
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,WAAW,EAEX,aAAa,EAEb,cAAc,EAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMlD,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE/D,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAuGrD,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAQ9E;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAK/D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,MAAM,EAAE,CAQhF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAEpE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,uBAAuB,GAAG,kBAAkB,CAAC,GACtE,OAAO,CAKT;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1D;AAqCD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,cAAc,CAwDhB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;IAEjF,IAAI,EAAE,UAAU;IAChB,QAAQ;IACR,IAAI;IACJ,MAAM;QAAI,IAAI;;EAEjB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAM1B;AAeD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,aAAa,CAiDf"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,WAAW,EAEX,aAAa,EAEb,cAAc,EAEd,cAAc,EACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE/D,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAuGrD,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAQ9E;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAK/D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,MAAM,EAAE,CAQhF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAEpE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,uBAAuB,GAAG,kBAAkB,CAAC,GACtE,OAAO,CAKT;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1D;AAqCD,MAAM,MAAM,gBAAgB,GACxB,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,GAC7C,CAAC,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,GAAG;IAAE,SAAS,EAAE,SAAS,cAAc,EAAE,CAAA;CAAE,CAAC,CAAC;AAE/F,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,gBAAgB,CAyDlB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;IAEjF,IAAI,EAAE,UAAU;IAChB,QAAQ;IACR,IAAI;IACJ,MAAM;QAAI,IAAI;;EAEjB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAM1B;AAeD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,aAAa,CAgDf"}