@agentshouse/mdruntime-adapter 0.1.0-cd028205a5103 → 0.1.0-cd23c45caa798
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 +285 -225
- package/dist/actions.d.ts +68 -1
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +196 -193
- package/dist/adapter.d.ts +1 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +384 -103
- package/dist/discovery.d.ts +7 -4
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +46 -13
- package/dist/gather.d.ts +2 -1
- package/dist/gather.d.ts.map +1 -1
- package/dist/gather.js +15 -20
- package/dist/handed.d.ts +15 -0
- package/dist/handed.d.ts.map +1 -0
- package/dist/handed.js +45 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/model.d.ts +1 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +6 -2
- package/dist/part.d.ts +13 -0
- package/dist/part.d.ts.map +1 -0
- package/dist/part.js +80 -0
- package/dist/read.d.ts +53 -16
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +265 -147
- package/dist/referrer.d.ts +7 -0
- package/dist/referrer.d.ts.map +1 -0
- package/dist/referrer.js +33 -0
- package/dist/refusal.d.ts +2 -5
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +6 -9
- package/dist/site.d.ts +1 -1
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +175 -58
- package/dist/stream.d.ts +4 -4
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +340 -42
- package/dist/transport.d.ts +64 -10
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +3 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/write.d.ts +14 -9
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +156 -37
- package/package.json +3 -4
- package/dist/links.d.ts +0 -20
- package/dist/links.d.ts.map +0 -1
- package/dist/links.js +0 -104
package/dist/site.js
CHANGED
|
@@ -1,79 +1,134 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { stepped } from '@agentshouse/mdruntime';
|
|
2
|
+
import { actionOutcome, SITE_SUBMIT } from './actions.js';
|
|
2
3
|
import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteTracked, } from './discovery.js';
|
|
3
|
-
import {
|
|
4
|
-
import { advancedScope,
|
|
4
|
+
import { partModels, streamedModels, viewModels } from './model.js';
|
|
5
|
+
import { advancedScope, bootstrapping, emptyScope, housePart, parseEnumeration, parseSiteParted, refreshFrom, viewOf, wholeView, } from './read.js';
|
|
6
|
+
import { PART_ATTEMPTS, unverifiedPart } from './part.js';
|
|
5
7
|
import { classifyDoor, classifyRead, discoveryFailure } from './refusal.js';
|
|
6
8
|
import { houseNotifications } from './stream.js';
|
|
7
|
-
import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT, } from './transport.js';
|
|
9
|
+
import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT, SITE_FILE_RECORD, SITE_FILES, } from './transport.js';
|
|
10
|
+
import { houseReferrer } from './referrer.js';
|
|
8
11
|
import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
|
|
9
12
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
13
|
+
function unfound() {
|
|
14
|
+
return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
|
|
15
|
+
}
|
|
10
16
|
function siteRoom(tracked) {
|
|
11
17
|
return {
|
|
12
18
|
name: tracked.handle,
|
|
13
19
|
locator: tracked.locator,
|
|
14
20
|
handle: tracked.handle,
|
|
15
21
|
roomVersion: roomVersion(tracked),
|
|
16
|
-
operations: {
|
|
17
|
-
replica: { selection: tracked.locator, admission: 'admitted' },
|
|
22
|
+
operations: { write: [], delete: [] },
|
|
23
|
+
replica: { selection: tracked.locator, admission: 'admitted', offline: 'open' },
|
|
18
24
|
providerOwnedPaths: [],
|
|
19
25
|
};
|
|
20
26
|
}
|
|
21
27
|
function settled(refused) {
|
|
22
28
|
return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;
|
|
23
29
|
}
|
|
24
|
-
export function createSiteAdapter(transport) {
|
|
30
|
+
export function createSiteAdapter(transport, snapshot = false) {
|
|
25
31
|
const notifications = houseNotifications(transport, 'site');
|
|
26
32
|
const tracked = new Map();
|
|
27
|
-
|
|
33
|
+
const expired = new Map();
|
|
34
|
+
function published(referrer) {
|
|
35
|
+
const named = houseReferrer(referrer, tracked);
|
|
36
|
+
return named === null || !tracked.has(named.locator) ? null : named;
|
|
37
|
+
}
|
|
38
|
+
function fileRoute(request) {
|
|
39
|
+
const named = published(request.kind === 'path' ? { room: request.locator, path: request.path } : request.referrer);
|
|
40
|
+
if (named === null) {
|
|
41
|
+
return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
|
|
42
|
+
}
|
|
43
|
+
if (request.fileRef === undefined)
|
|
44
|
+
return unfound();
|
|
45
|
+
const { room_ref, path, record } = named.referrer;
|
|
46
|
+
return `${SITE_FILES}${room_ref}/${encodeURIComponent(request.fileRef)}/${path === undefined
|
|
47
|
+
? `${SITE_FILE_RECORD}/${encodeURIComponent(record)}`
|
|
48
|
+
: encodeURIComponent(path)}`;
|
|
49
|
+
}
|
|
50
|
+
async function enumerated(entry, from, page) {
|
|
28
51
|
const answer = await transport.door(SITE_DOOR_ENUMERATE, {
|
|
29
|
-
positions: [
|
|
52
|
+
positions: [
|
|
53
|
+
page === undefined
|
|
54
|
+
? presented(entry.authority, from)
|
|
55
|
+
: {
|
|
56
|
+
...presented(entry.authority, { position: page.after, logEpoch: from.logEpoch }),
|
|
57
|
+
page: { through: page.through, read: page.read },
|
|
58
|
+
},
|
|
59
|
+
],
|
|
30
60
|
});
|
|
31
61
|
const classified = classifyRead(answer.status, answer.body, entry.locator);
|
|
32
62
|
if (classified !== null)
|
|
33
63
|
return classified;
|
|
34
|
-
|
|
64
|
+
const found = parseEnumeration(answer.body, 'site');
|
|
65
|
+
if (found === null)
|
|
66
|
+
return UNCERTAIN;
|
|
67
|
+
return viewOf(found, entry) ?? { kind: 'room-not-readable', locator: entry.locator };
|
|
35
68
|
}
|
|
36
|
-
async function
|
|
37
|
-
const
|
|
69
|
+
async function enumeration(entry, from) {
|
|
70
|
+
const first = await enumerated(entry, from);
|
|
71
|
+
return 'kind' in first ? first : wholeView(first, (page) => enumerated(entry, from, page));
|
|
72
|
+
}
|
|
73
|
+
async function partedRoom(entry) {
|
|
74
|
+
const cut = expired.get(entry.locator);
|
|
75
|
+
const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}${cut === undefined ? '' : `?expired=${cut}`}`);
|
|
38
76
|
const classified = classifyDoor(answer.status, answer.body, entry.locator);
|
|
39
77
|
if (classified !== null)
|
|
40
|
-
return
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
return classified;
|
|
79
|
+
const room = parseSiteParted(answer.body);
|
|
80
|
+
return room === null || room.anchor !== entry.authority ? UNCERTAIN : room;
|
|
81
|
+
}
|
|
82
|
+
async function fetchedPart(entry, room, listed) {
|
|
83
|
+
for (let attempt = 0; attempt < PART_ATTEMPTS; attempt += 1) {
|
|
84
|
+
const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}?part=${encodeURIComponent(listed.part)}`);
|
|
85
|
+
const failure = classifyRead(answer.status, answer.body, entry.locator);
|
|
86
|
+
if (failure?.kind === 'beyond-horizon')
|
|
87
|
+
expired.set(entry.locator, room.position);
|
|
88
|
+
if (failure !== null)
|
|
89
|
+
return failure;
|
|
90
|
+
const scope = await housePart(room, answer.body, listed, 'site');
|
|
91
|
+
if (scope !== null)
|
|
92
|
+
return scope;
|
|
93
|
+
}
|
|
94
|
+
return unverifiedPart(entry.locator);
|
|
95
|
+
}
|
|
96
|
+
async function caughtUp(entry, continued) {
|
|
97
|
+
const listed = continued.room.parts[continued.next];
|
|
98
|
+
const scope = listed === undefined
|
|
99
|
+
? emptyScope(continued.room)
|
|
100
|
+
: await fetchedPart(entry, continued.room, listed);
|
|
101
|
+
if ('kind' in scope)
|
|
102
|
+
return scope;
|
|
103
|
+
if (continued.room.parts.length > 1 || roomVersion(scope) === roomVersion(entry))
|
|
104
|
+
return scope;
|
|
105
|
+
const view = await enumeration(entry, scope);
|
|
106
|
+
if ('kind' in view)
|
|
107
|
+
return settled(view);
|
|
108
|
+
return stepped(advancedScope(scope, view));
|
|
53
109
|
}
|
|
54
110
|
async function refreshed(entry, fromRoomVersion) {
|
|
55
111
|
const from = logPosition(fromRoomVersion);
|
|
56
112
|
if (from === null)
|
|
57
113
|
return { kind: 'beyond-horizon' };
|
|
58
|
-
const streamed = notifications.advance(entry, from);
|
|
114
|
+
const streamed = await stepped(notifications.advance(entry, from));
|
|
59
115
|
if (streamed !== null) {
|
|
60
116
|
const models = await streamedModels(streamed.schemas, entry, 'site');
|
|
61
117
|
return models === undefined ? streamed.page : { ...streamed.page, models };
|
|
62
118
|
}
|
|
63
|
-
const
|
|
64
|
-
if ('kind' in
|
|
65
|
-
return
|
|
66
|
-
const view = viewOf(found, entry);
|
|
67
|
-
if (view === undefined)
|
|
68
|
-
return { kind: 'room-not-readable', locator: entry.locator };
|
|
119
|
+
const view = await enumeration(entry, from);
|
|
120
|
+
if ('kind' in view)
|
|
121
|
+
return view;
|
|
69
122
|
notifications.reach(entry.authority, view);
|
|
70
|
-
const answer = refreshFrom(view, fromRoomVersion);
|
|
123
|
+
const answer = await refreshFrom(view, fromRoomVersion);
|
|
71
124
|
if (answer.kind !== 'net-advancement')
|
|
72
125
|
return answer;
|
|
73
126
|
const models = await viewModels(view, entry);
|
|
74
127
|
return models === undefined ? answer : { ...answer, models };
|
|
75
128
|
}
|
|
76
129
|
return {
|
|
130
|
+
localSaves: true,
|
|
131
|
+
exhaustiveDiscovery: true,
|
|
77
132
|
async authorize() {
|
|
78
133
|
return {};
|
|
79
134
|
},
|
|
@@ -96,14 +151,31 @@ export function createSiteAdapter(transport) {
|
|
|
96
151
|
const entry = tracked.get(request.locator);
|
|
97
152
|
if (entry === undefined)
|
|
98
153
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
154
|
+
let continued;
|
|
155
|
+
if (request.pageToken === undefined) {
|
|
156
|
+
const room = await partedRoom(entry);
|
|
157
|
+
if ('kind' in room)
|
|
158
|
+
return room;
|
|
159
|
+
continued = { room, next: 0, seen: [] };
|
|
160
|
+
}
|
|
161
|
+
else
|
|
162
|
+
continued = JSON.parse(request.pageToken);
|
|
163
|
+
const scope = await caughtUp(entry, continued);
|
|
164
|
+
if ('kind' in scope)
|
|
165
|
+
return scope;
|
|
166
|
+
notifications.reach(entry.authority, scope);
|
|
167
|
+
const next = continued.next + 1;
|
|
168
|
+
const more = next < continued.room.parts.length;
|
|
169
|
+
const seen = [
|
|
170
|
+
...continued.seen,
|
|
171
|
+
...entry.schemas.filter((schema) => scope.files.some((file) => file.path === schema)),
|
|
172
|
+
];
|
|
173
|
+
const models = await partModels(scope, entry, new Set(seen), !more);
|
|
174
|
+
return {
|
|
175
|
+
...(await stepped(bootstrapping(scope))),
|
|
176
|
+
...(models === undefined ? {} : { models }),
|
|
177
|
+
...(more ? { pageToken: JSON.stringify({ ...continued, next, seen }) } : {}),
|
|
178
|
+
};
|
|
107
179
|
},
|
|
108
180
|
async refresh(_authorization, request) {
|
|
109
181
|
const entry = tracked.get(request.locator);
|
|
@@ -111,14 +183,47 @@ export function createSiteAdapter(transport) {
|
|
|
111
183
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
112
184
|
if (request.pageToken !== undefined)
|
|
113
185
|
return UNCERTAIN;
|
|
186
|
+
if (snapshot) {
|
|
187
|
+
return request.fromRoomVersion === roomVersion(entry)
|
|
188
|
+
? { kind: 'still-current' }
|
|
189
|
+
: { kind: 'beyond-horizon' };
|
|
190
|
+
}
|
|
114
191
|
return refreshed(entry, request.fromRoomVersion);
|
|
115
192
|
},
|
|
116
193
|
async mutate() {
|
|
117
|
-
return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {} };
|
|
194
|
+
return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {}, retryable: false };
|
|
118
195
|
},
|
|
119
196
|
async history() {
|
|
120
197
|
return { kind: 'no-history' };
|
|
121
198
|
},
|
|
199
|
+
async binary(_authorization, request) {
|
|
200
|
+
const route = fileRoute(request);
|
|
201
|
+
if (typeof route !== 'string')
|
|
202
|
+
return route;
|
|
203
|
+
const read = await transport.download(route);
|
|
204
|
+
if (read.status === 404)
|
|
205
|
+
return unfound();
|
|
206
|
+
return read.status === 200 && read.blob !== null
|
|
207
|
+
? { kind: 'binary', blob: read.blob }
|
|
208
|
+
: UNCERTAIN;
|
|
209
|
+
},
|
|
210
|
+
async link(_authorization, request) {
|
|
211
|
+
const route = fileRoute(request);
|
|
212
|
+
if (typeof route !== 'string')
|
|
213
|
+
return route;
|
|
214
|
+
return {
|
|
215
|
+
kind: 'link',
|
|
216
|
+
url: route,
|
|
217
|
+
name: request.path.slice(request.path.lastIndexOf('/') + 1),
|
|
218
|
+
};
|
|
219
|
+
},
|
|
220
|
+
referrerScope(referrer) {
|
|
221
|
+
const named = published(referrer);
|
|
222
|
+
if (named === null)
|
|
223
|
+
return null;
|
|
224
|
+
const { path } = named.referrer;
|
|
225
|
+
return { locator: named.locator, ...(path === undefined ? {} : { path }) };
|
|
226
|
+
},
|
|
122
227
|
reached(locator, version, target) {
|
|
123
228
|
return reachedVersion(version, target, tracked.get(locator)?.logEpoch);
|
|
124
229
|
},
|
|
@@ -126,27 +231,39 @@ export function createSiteAdapter(transport) {
|
|
|
126
231
|
return followsVersion(version, next);
|
|
127
232
|
},
|
|
128
233
|
async action(_authorization, request) {
|
|
129
|
-
if (request.name !==
|
|
130
|
-
return {
|
|
234
|
+
if (request.name !== SITE_SUBMIT) {
|
|
235
|
+
return {
|
|
236
|
+
kind: 'rejected',
|
|
237
|
+
code: 'action-unimplemented',
|
|
238
|
+
fields: { name: request.name },
|
|
239
|
+
retryable: false,
|
|
240
|
+
};
|
|
131
241
|
}
|
|
132
242
|
if (!transport.online())
|
|
133
243
|
return UNCERTAIN;
|
|
134
|
-
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input),
|
|
244
|
+
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input), SITE_SUBMIT);
|
|
135
245
|
},
|
|
136
|
-
roomStream:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
246
|
+
roomStream: snapshot
|
|
247
|
+
? undefined
|
|
248
|
+
: {
|
|
249
|
+
hold(rooms) {
|
|
250
|
+
notifications.send(rooms.flatMap((room) => {
|
|
251
|
+
const entry = tracked.get(room.locator);
|
|
252
|
+
const at = logPosition(room.roomVersion);
|
|
253
|
+
if (entry === undefined || at === null)
|
|
254
|
+
return [];
|
|
255
|
+
notifications.reach(entry.authority, at);
|
|
256
|
+
return [presented(entry.authority, at)];
|
|
257
|
+
}));
|
|
258
|
+
},
|
|
259
|
+
reopen: notifications.reopen,
|
|
260
|
+
observe: notifications.observe,
|
|
261
|
+
published(locator, roomVersion) {
|
|
262
|
+
const at = logPosition(roomVersion);
|
|
263
|
+
if (at !== null)
|
|
264
|
+
notifications.published(locator, at);
|
|
265
|
+
},
|
|
146
266
|
},
|
|
147
|
-
reopen: notifications.reopen,
|
|
148
|
-
observe: notifications.observe,
|
|
149
|
-
},
|
|
150
267
|
serviceMode: notifications.serviceMode,
|
|
151
268
|
};
|
|
152
269
|
}
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ConversationStream, type RefreshPage, type RoomStreamEvent, type ServiceModeSignal, type StreamReceipts } from '@agentshouse/mdruntime';
|
|
2
2
|
import type { TrackedAuthority } from './discovery.js';
|
|
3
3
|
import type { HouseDoor, HouseHeldRoom, HouseMode, HouseStreamEntry } from './transport.js';
|
|
4
4
|
import { type LogPosition } from './version.js';
|
|
5
5
|
export type HeldRevision = (path: string, revision: string) => boolean;
|
|
6
6
|
export type StreamedAdvancement = {
|
|
7
7
|
page: RefreshPage;
|
|
8
|
-
entries: readonly HouseStreamEntry[];
|
|
9
8
|
schemas: ReadonlyMap<string, HouseStreamEntry>;
|
|
10
9
|
};
|
|
11
10
|
export type HouseNotifications = {
|
|
12
11
|
runtime: string;
|
|
13
|
-
observe(notify: (event: RoomStreamEvent) => void): () => void;
|
|
12
|
+
observe(notify: (event: RoomStreamEvent) => void, receipts: StreamReceipts): () => void;
|
|
14
13
|
send(rooms: readonly HouseHeldRoom[]): void;
|
|
14
|
+
published(locator: string, at: LogPosition): void;
|
|
15
15
|
reopen(): void;
|
|
16
16
|
track(authorities: readonly TrackedAuthority[]): void;
|
|
17
17
|
reach(authority: string, at: LogPosition): void;
|
|
18
|
-
advance(tracked: TrackedAuthority, from: LogPosition, holds?: HeldRevision): StreamedAdvancement | null
|
|
18
|
+
advance(tracked: TrackedAuthority, from: LogPosition, holds?: HeldRevision): Generator<number, StreamedAdvancement | null, void>;
|
|
19
19
|
conversations: ConversationStream;
|
|
20
20
|
serviceMode: ServiceModeSignal;
|
|
21
21
|
};
|
package/dist/stream.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,kBAAkB,EAEvB,KAAK,WAAW,EAChB,KAAK,eAAe,EAEpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EAEb,SAAS,EAET,gBAAgB,EAEjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AA0C7D,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;AAEvE,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI,CAAC;IACxF,IAAI,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAAC;IAC5C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAClD,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,OAAO,CACL,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,KAAK,CAAC,EAAE,YAAY,GACnB,SAAS,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC;IACvD,aAAa,EAAE,kBAAkB,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAmFF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CA0iB5F"}
|