@agentshouse/mdruntime-adapter 0.1.0-cca5d676bc88e → 0.1.0-ccd2ccb1f7214
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 +278 -210
- package/dist/actions.d.ts +63 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +157 -138
- package/dist/adapter.d.ts +1 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +322 -100
- package/dist/discovery.d.ts +4 -4
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +26 -12
- package/dist/gather.d.ts +1 -0
- package/dist/gather.d.ts.map +1 -1
- package/dist/gather.js +11 -6
- package/dist/handed.d.ts +15 -0
- package/dist/handed.d.ts.map +1 -0
- package/dist/handed.js +38 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/model.d.ts +1 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +21 -7
- package/dist/read.d.ts +35 -7
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +160 -79
- package/dist/referrer.d.ts +7 -0
- package/dist/referrer.d.ts.map +1 -0
- package/dist/referrer.js +35 -0
- package/dist/refusal.d.ts +5 -9
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +31 -17
- package/dist/site.d.ts +1 -1
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +189 -54
- package/dist/stream.d.ts +4 -2
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +330 -16
- package/dist/transport.d.ts +64 -11
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +3 -1
- 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 +3 -9
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +97 -20
- 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,16 +1,22 @@
|
|
|
1
|
-
import { actionOutcome } from './actions.js';
|
|
1
|
+
import { actionOutcome, SITE_SUBMIT } from './actions.js';
|
|
2
2
|
import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteTracked, } from './discovery.js';
|
|
3
|
-
import {
|
|
4
|
-
import { advancedScope, bootstrapOf, parseEnumeration, parseSiteBootstrap, refreshFrom, viewOf, } from './read.js';
|
|
5
|
-
import {
|
|
3
|
+
import { partModels, streamedModels, viewModels } from './model.js';
|
|
4
|
+
import { advancedScope, bootstrapOf, parseEnumeration, parseSiteBootstrap, refreshFrom, siteBootstrapNext, siteBootstrapOffset, viewOf, wholeView, } from './read.js';
|
|
5
|
+
import { sha256Hex } from './digest.js';
|
|
6
|
+
import { classifyDoor, classifyRead, discoveryFailure } from './refusal.js';
|
|
6
7
|
import { houseNotifications } from './stream.js';
|
|
7
|
-
import {
|
|
8
|
+
import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT, SITE_FILE_RECORD, SITE_FILES, } from './transport.js';
|
|
9
|
+
import { houseReferrer } from './referrer.js';
|
|
8
10
|
import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
|
|
9
11
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
12
|
+
function unfound() {
|
|
13
|
+
return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
|
|
14
|
+
}
|
|
10
15
|
function siteRoom(tracked) {
|
|
11
16
|
return {
|
|
12
17
|
name: tracked.handle,
|
|
13
18
|
locator: tracked.locator,
|
|
19
|
+
handle: tracked.handle,
|
|
14
20
|
roomVersion: roomVersion(tracked),
|
|
15
21
|
operations: { read: [''], sync: [''], write: [], delete: [] },
|
|
16
22
|
replica: { selection: tracked.locator, admission: 'admitted' },
|
|
@@ -20,35 +26,109 @@ function siteRoom(tracked) {
|
|
|
20
26
|
function settled(refused) {
|
|
21
27
|
return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;
|
|
22
28
|
}
|
|
23
|
-
export function createSiteAdapter(transport) {
|
|
29
|
+
export function createSiteAdapter(transport, snapshot = false) {
|
|
24
30
|
const notifications = houseNotifications(transport, 'site');
|
|
25
31
|
const tracked = new Map();
|
|
26
|
-
|
|
32
|
+
function published(referrer) {
|
|
33
|
+
const named = houseReferrer(referrer, tracked);
|
|
34
|
+
return named === null || !tracked.has(named.locator) ? null : named;
|
|
35
|
+
}
|
|
36
|
+
function fileRoute(request) {
|
|
37
|
+
const named = published(request.kind === 'path' ? { room: request.locator, path: request.path } : request.referrer);
|
|
38
|
+
if (named === null) {
|
|
39
|
+
return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
|
|
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)}`;
|
|
47
|
+
}
|
|
48
|
+
async function enumerated(entry, from, page) {
|
|
27
49
|
const answer = await transport.door(SITE_DOOR_ENUMERATE, {
|
|
28
|
-
positions: [
|
|
50
|
+
positions: [
|
|
51
|
+
page === undefined
|
|
52
|
+
? presented(entry.authority, from)
|
|
53
|
+
: {
|
|
54
|
+
...presented(entry.authority, { position: page.after, logEpoch: from.logEpoch }),
|
|
55
|
+
page: { through: page.through, read: page.read },
|
|
56
|
+
},
|
|
57
|
+
],
|
|
29
58
|
});
|
|
30
|
-
const classified =
|
|
59
|
+
const classified = classifyRead(answer.status, answer.body, entry.locator);
|
|
31
60
|
if (classified !== null)
|
|
32
61
|
return classified;
|
|
33
|
-
|
|
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 };
|
|
34
66
|
}
|
|
35
|
-
async function
|
|
36
|
-
const
|
|
67
|
+
async function enumeration(entry, from) {
|
|
68
|
+
const first = await enumerated(entry, from);
|
|
69
|
+
return 'kind' in first ? first : wholeView(first, (page) => enumerated(entry, from, page));
|
|
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('&')}`}`);
|
|
37
77
|
const classified = classifyDoor(answer.status, answer.body, entry.locator);
|
|
38
78
|
if (classified !== null)
|
|
39
|
-
return { failure:
|
|
79
|
+
return { failure: classified };
|
|
40
80
|
const scope = parseSiteBootstrap(answer.body);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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)
|
|
115
|
+
return part;
|
|
116
|
+
const next = siteBootstrapNext(part.body);
|
|
117
|
+
const offset = siteBootstrapOffset(part.body);
|
|
118
|
+
if (offset !== null) {
|
|
119
|
+
if (next === null)
|
|
120
|
+
return { failure: UNCERTAIN };
|
|
121
|
+
const scope = await assembled(entry, part.scope, next, offset);
|
|
122
|
+
return 'kind' in scope ? { failure: scope } : { scope, next };
|
|
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 };
|
|
52
132
|
}
|
|
53
133
|
async function refreshed(entry, fromRoomVersion) {
|
|
54
134
|
const from = logPosition(fromRoomVersion);
|
|
@@ -59,12 +139,9 @@ export function createSiteAdapter(transport) {
|
|
|
59
139
|
const models = await streamedModels(streamed.schemas, entry, 'site');
|
|
60
140
|
return models === undefined ? streamed.page : { ...streamed.page, models };
|
|
61
141
|
}
|
|
62
|
-
const
|
|
63
|
-
if ('kind' in
|
|
64
|
-
return
|
|
65
|
-
const view = viewOf(found, entry);
|
|
66
|
-
if (view === undefined)
|
|
67
|
-
return { kind: 'room-not-readable', locator: entry.locator };
|
|
142
|
+
const view = await enumeration(entry, from);
|
|
143
|
+
if ('kind' in view)
|
|
144
|
+
return view;
|
|
68
145
|
notifications.reach(entry.authority, view);
|
|
69
146
|
const answer = refreshFrom(view, fromRoomVersion);
|
|
70
147
|
if (answer.kind !== 'net-advancement')
|
|
@@ -73,14 +150,16 @@ export function createSiteAdapter(transport) {
|
|
|
73
150
|
return models === undefined ? answer : { ...answer, models };
|
|
74
151
|
}
|
|
75
152
|
return {
|
|
153
|
+
localSaves: true,
|
|
154
|
+
exhaustiveDiscovery: true,
|
|
76
155
|
async authorize() {
|
|
77
156
|
return {};
|
|
78
157
|
},
|
|
79
158
|
async discover() {
|
|
80
159
|
const answer = await transport.read(SITE_DOOR_DISCOVER);
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
return
|
|
160
|
+
const failed = discoveryFailure(answer.status, answer.body);
|
|
161
|
+
if (failed !== null)
|
|
162
|
+
return failed;
|
|
84
163
|
const document = parseSiteDiscovery(answer.body);
|
|
85
164
|
if (document === null)
|
|
86
165
|
return UNCERTAIN;
|
|
@@ -95,14 +174,24 @@ export function createSiteAdapter(transport) {
|
|
|
95
174
|
const entry = tracked.get(request.locator);
|
|
96
175
|
if (entry === undefined)
|
|
97
176
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
177
|
+
const continued = request.pageToken === undefined
|
|
178
|
+
? null
|
|
179
|
+
: JSON.parse(request.pageToken);
|
|
180
|
+
const held = await caughtUp(entry, continued?.after ?? null);
|
|
101
181
|
if ('failure' in held)
|
|
102
182
|
return held.failure;
|
|
103
183
|
notifications.reach(entry.authority, held.scope);
|
|
104
|
-
const
|
|
105
|
-
|
|
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
|
+
};
|
|
106
195
|
},
|
|
107
196
|
async refresh(_authorization, request) {
|
|
108
197
|
const entry = tracked.get(request.locator);
|
|
@@ -110,14 +199,47 @@ export function createSiteAdapter(transport) {
|
|
|
110
199
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
111
200
|
if (request.pageToken !== undefined)
|
|
112
201
|
return UNCERTAIN;
|
|
202
|
+
if (snapshot) {
|
|
203
|
+
return request.fromRoomVersion === roomVersion(entry)
|
|
204
|
+
? { kind: 'still-current' }
|
|
205
|
+
: { kind: 'beyond-horizon' };
|
|
206
|
+
}
|
|
113
207
|
return refreshed(entry, request.fromRoomVersion);
|
|
114
208
|
},
|
|
115
209
|
async mutate() {
|
|
116
|
-
return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {} };
|
|
210
|
+
return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {}, retryable: false };
|
|
117
211
|
},
|
|
118
212
|
async history() {
|
|
119
213
|
return { kind: 'no-history' };
|
|
120
214
|
},
|
|
215
|
+
async binary(_authorization, request) {
|
|
216
|
+
const route = fileRoute(request);
|
|
217
|
+
if (typeof route !== 'string')
|
|
218
|
+
return route;
|
|
219
|
+
const read = await transport.download(route);
|
|
220
|
+
if (read.status === 404)
|
|
221
|
+
return unfound();
|
|
222
|
+
return read.status === 200 && read.blob !== null
|
|
223
|
+
? { kind: 'binary', blob: read.blob }
|
|
224
|
+
: UNCERTAIN;
|
|
225
|
+
},
|
|
226
|
+
async link(_authorization, request) {
|
|
227
|
+
const route = fileRoute(request);
|
|
228
|
+
if (typeof route !== 'string')
|
|
229
|
+
return route;
|
|
230
|
+
return {
|
|
231
|
+
kind: 'link',
|
|
232
|
+
url: route,
|
|
233
|
+
name: request.path.slice(request.path.lastIndexOf('/') + 1),
|
|
234
|
+
};
|
|
235
|
+
},
|
|
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
|
+
},
|
|
121
243
|
reached(locator, version, target) {
|
|
122
244
|
return reachedVersion(version, target, tracked.get(locator)?.logEpoch);
|
|
123
245
|
},
|
|
@@ -125,26 +247,39 @@ export function createSiteAdapter(transport) {
|
|
|
125
247
|
return followsVersion(version, next);
|
|
126
248
|
},
|
|
127
249
|
async action(_authorization, request) {
|
|
128
|
-
if (request.name !==
|
|
129
|
-
return {
|
|
250
|
+
if (request.name !== SITE_SUBMIT) {
|
|
251
|
+
return {
|
|
252
|
+
kind: 'rejected',
|
|
253
|
+
code: 'action-unimplemented',
|
|
254
|
+
fields: { name: request.name },
|
|
255
|
+
retryable: false,
|
|
256
|
+
};
|
|
130
257
|
}
|
|
131
258
|
if (!transport.online())
|
|
132
259
|
return UNCERTAIN;
|
|
133
|
-
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input),
|
|
260
|
+
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input), SITE_SUBMIT);
|
|
134
261
|
},
|
|
135
|
-
roomStream:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
262
|
+
roomStream: snapshot
|
|
263
|
+
? undefined
|
|
264
|
+
: {
|
|
265
|
+
hold(rooms) {
|
|
266
|
+
notifications.send(rooms.flatMap((room) => {
|
|
267
|
+
const entry = tracked.get(room.locator);
|
|
268
|
+
const at = logPosition(room.roomVersion);
|
|
269
|
+
if (entry === undefined || at === null)
|
|
270
|
+
return [];
|
|
271
|
+
notifications.reach(entry.authority, at);
|
|
272
|
+
return [presented(entry.authority, at)];
|
|
273
|
+
}));
|
|
274
|
+
},
|
|
275
|
+
reopen: notifications.reopen,
|
|
276
|
+
observe: notifications.observe,
|
|
277
|
+
published(locator, roomVersion) {
|
|
278
|
+
const at = logPosition(roomVersion);
|
|
279
|
+
if (at !== null)
|
|
280
|
+
notifications.published(locator, at);
|
|
281
|
+
},
|
|
145
282
|
},
|
|
146
|
-
observe: notifications.observe,
|
|
147
|
-
},
|
|
148
283
|
serviceMode: notifications.serviceMode,
|
|
149
284
|
};
|
|
150
285
|
}
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConversationStream, RefreshPage, RoomStreamEvent, ServiceModeSignal } from '@agentshouse/mdruntime';
|
|
1
|
+
import type { ConversationStream, RefreshPage, RoomStreamEvent, ServiceModeSignal, 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';
|
|
@@ -10,8 +10,10 @@ export type StreamedAdvancement = {
|
|
|
10
10
|
};
|
|
11
11
|
export type HouseNotifications = {
|
|
12
12
|
runtime: string;
|
|
13
|
-
observe(notify: (event: RoomStreamEvent) => void): () => void;
|
|
13
|
+
observe(notify: (event: RoomStreamEvent) => void, receipts: StreamReceipts): () => void;
|
|
14
14
|
send(rooms: readonly HouseHeldRoom[]): void;
|
|
15
|
+
published(locator: string, at: LogPosition): void;
|
|
16
|
+
reopen(): void;
|
|
15
17
|
track(authorities: readonly TrackedAuthority[]): void;
|
|
16
18
|
reach(authority: string, at: LogPosition): void;
|
|
17
19
|
advance(tracked: TrackedAuthority, from: LogPosition, holds?: HeldRevision): StreamedAdvancement | null;
|
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,KAAK,EAGV,kBAAkB,EAElB,WAAW,EACX,eAAe,EAEf,iBAAiB,EACjB,cAAc,EAEf,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,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,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,mBAAmB,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,kBAAkB,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAkFF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CAqjB5F"}
|