@agentshouse/mdruntime 0.1.0-cbbae1fff01c6 → 0.1.0-cc00e9289ddf4

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.
Files changed (200) hide show
  1. package/README.md +17 -15
  2. package/dist/acceptance.d.ts.map +1 -1
  3. package/dist/acceptance.js +14 -23
  4. package/dist/act-lanes.d.ts +30 -0
  5. package/dist/act-lanes.d.ts.map +1 -0
  6. package/dist/act-lanes.js +225 -0
  7. package/dist/actions.d.ts +8 -2
  8. package/dist/actions.d.ts.map +1 -1
  9. package/dist/actions.js +114 -63
  10. package/dist/adapter.d.ts +30 -12
  11. package/dist/adapter.d.ts.map +1 -1
  12. package/dist/attached-model.d.ts +0 -1
  13. package/dist/attached-model.d.ts.map +1 -1
  14. package/dist/attached-model.js +0 -5
  15. package/dist/chat-types.d.ts +0 -2
  16. package/dist/chat-types.d.ts.map +1 -1
  17. package/dist/chat-types.js +0 -2
  18. package/dist/client.d.ts +8 -18
  19. package/dist/client.d.ts.map +1 -1
  20. package/dist/client.js +27 -15
  21. package/dist/compile.d.ts +2 -0
  22. package/dist/compile.d.ts.map +1 -1
  23. package/dist/compile.js +17 -4
  24. package/dist/connection.d.ts.map +1 -1
  25. package/dist/connection.js +15 -13
  26. package/dist/conversation-live.d.ts +23 -8
  27. package/dist/conversation-live.d.ts.map +1 -1
  28. package/dist/conversation-live.js +21 -9
  29. package/dist/conversation-row.d.ts +2 -0
  30. package/dist/conversation-row.d.ts.map +1 -1
  31. package/dist/conversation-row.js +2 -0
  32. package/dist/conversation.d.ts +27 -5
  33. package/dist/conversation.d.ts.map +1 -1
  34. package/dist/conversation.js +279 -168
  35. package/dist/discovery.d.ts.map +1 -1
  36. package/dist/discovery.js +8 -6
  37. package/dist/durability.d.ts +4 -0
  38. package/dist/durability.d.ts.map +1 -1
  39. package/dist/durability.js +4 -0
  40. package/dist/entry.js +1 -1
  41. package/dist/expectation.d.ts +25 -14
  42. package/dist/expectation.d.ts.map +1 -1
  43. package/dist/expectation.js +51 -20
  44. package/dist/failure.d.ts +2 -0
  45. package/dist/failure.d.ts.map +1 -1
  46. package/dist/failure.js +3 -0
  47. package/dist/figures.d.ts.map +1 -1
  48. package/dist/figures.js +4 -2
  49. package/dist/file.d.ts.map +1 -1
  50. package/dist/file.js +2 -1
  51. package/dist/host.d.ts +1 -0
  52. package/dist/host.d.ts.map +1 -1
  53. package/dist/host.js +39 -11
  54. package/dist/index.d.ts +11 -8
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +9 -6
  57. package/dist/install.d.ts +10 -4
  58. package/dist/install.d.ts.map +1 -1
  59. package/dist/install.js +45 -46
  60. package/dist/lifecycle.d.ts.map +1 -1
  61. package/dist/lifecycle.js +22 -16
  62. package/dist/listing.d.ts +7 -3
  63. package/dist/listing.d.ts.map +1 -1
  64. package/dist/listing.js +26 -13
  65. package/dist/live.d.ts +5 -3
  66. package/dist/live.d.ts.map +1 -1
  67. package/dist/live.js +71 -30
  68. package/dist/locks.d.ts.map +1 -1
  69. package/dist/locks.js +2 -3
  70. package/dist/lost.d.ts.map +1 -1
  71. package/dist/lost.js +2 -3
  72. package/dist/media.d.ts.map +1 -1
  73. package/dist/media.js +7 -10
  74. package/dist/memory.d.ts +3 -1
  75. package/dist/memory.d.ts.map +1 -1
  76. package/dist/memory.js +50 -22
  77. package/dist/messages.d.ts +12 -3
  78. package/dist/messages.d.ts.map +1 -1
  79. package/dist/messages.js +24 -10
  80. package/dist/models.d.ts.map +1 -1
  81. package/dist/models.js +5 -8
  82. package/dist/observation.d.ts +27 -12
  83. package/dist/observation.d.ts.map +1 -1
  84. package/dist/observation.js +173 -69
  85. package/dist/opening.d.ts.map +1 -1
  86. package/dist/opening.js +3 -9
  87. package/dist/outcome.d.ts +7 -0
  88. package/dist/outcome.d.ts.map +1 -1
  89. package/dist/outcome.js +23 -2
  90. package/dist/overlay.d.ts +3 -0
  91. package/dist/overlay.d.ts.map +1 -1
  92. package/dist/overlay.js +8 -4
  93. package/dist/page-metadata.d.ts +8 -0
  94. package/dist/page-metadata.d.ts.map +1 -0
  95. package/dist/page-metadata.js +19 -0
  96. package/dist/parts.d.ts +2 -9
  97. package/dist/parts.d.ts.map +1 -1
  98. package/dist/parts.js +6 -14
  99. package/dist/preparation.d.ts +27 -6
  100. package/dist/preparation.d.ts.map +1 -1
  101. package/dist/preparation.js +137 -56
  102. package/dist/presence.d.ts +7 -1
  103. package/dist/presence.d.ts.map +1 -1
  104. package/dist/presence.js +22 -9
  105. package/dist/queries.d.ts +2 -2
  106. package/dist/queries.d.ts.map +1 -1
  107. package/dist/queries.js +62 -24
  108. package/dist/questions.d.ts +0 -5
  109. package/dist/questions.d.ts.map +1 -1
  110. package/dist/questions.js +0 -7
  111. package/dist/queue.d.ts +2 -2
  112. package/dist/queue.d.ts.map +1 -1
  113. package/dist/queue.js +25 -30
  114. package/dist/reach.d.ts +2 -3
  115. package/dist/reach.d.ts.map +1 -1
  116. package/dist/reach.js +75 -21
  117. package/dist/react.d.ts +7 -5
  118. package/dist/react.d.ts.map +1 -1
  119. package/dist/react.js +28 -5
  120. package/dist/readiness.d.ts +9 -3
  121. package/dist/readiness.d.ts.map +1 -1
  122. package/dist/readiness.js +3 -5
  123. package/dist/reads.d.ts +3 -1
  124. package/dist/reads.d.ts.map +1 -1
  125. package/dist/reads.js +5 -1
  126. package/dist/recovery.d.ts +3 -1
  127. package/dist/recovery.d.ts.map +1 -1
  128. package/dist/recovery.js +29 -7
  129. package/dist/refusal.d.ts.map +1 -1
  130. package/dist/refusal.js +1 -3
  131. package/dist/retried.d.ts +30 -0
  132. package/dist/retried.d.ts.map +1 -0
  133. package/dist/retried.js +72 -0
  134. package/dist/room-draft.d.ts +2 -2
  135. package/dist/room-draft.d.ts.map +1 -1
  136. package/dist/room-draft.js +26 -21
  137. package/dist/rows.d.ts +2 -0
  138. package/dist/rows.d.ts.map +1 -1
  139. package/dist/rows.js +3 -0
  140. package/dist/runtime.d.ts +2 -2
  141. package/dist/runtime.d.ts.map +1 -1
  142. package/dist/save.d.ts +1 -0
  143. package/dist/save.d.ts.map +1 -1
  144. package/dist/save.js +105 -55
  145. package/dist/saves.d.ts.map +1 -1
  146. package/dist/saves.js +3 -6
  147. package/dist/seed.d.ts.map +1 -1
  148. package/dist/seed.js +2 -2
  149. package/dist/shown.d.ts +3 -2
  150. package/dist/shown.d.ts.map +1 -1
  151. package/dist/shown.js +58 -39
  152. package/dist/socket/lanes.d.ts +12 -4
  153. package/dist/socket/lanes.d.ts.map +1 -1
  154. package/dist/socket/lanes.js +34 -8
  155. package/dist/socket.d.ts +3 -3
  156. package/dist/socket.d.ts.map +1 -1
  157. package/dist/socket.js +3 -9
  158. package/dist/source.d.ts +0 -7
  159. package/dist/source.d.ts.map +1 -1
  160. package/dist/store/installs.d.ts +2 -2
  161. package/dist/store/installs.d.ts.map +1 -1
  162. package/dist/store/installs.js +10 -4
  163. package/dist/store/readiness.d.ts +5 -4
  164. package/dist/store/readiness.d.ts.map +1 -1
  165. package/dist/store/readiness.js +28 -12
  166. package/dist/store/records.d.ts +11 -4
  167. package/dist/store/records.d.ts.map +1 -1
  168. package/dist/store/records.js +56 -20
  169. package/dist/store/rooms-shown.d.ts +8 -0
  170. package/dist/store/rooms-shown.d.ts.map +1 -0
  171. package/dist/store/rooms-shown.js +13 -0
  172. package/dist/store.d.ts +9 -6
  173. package/dist/store.d.ts.map +1 -1
  174. package/dist/store.js +11 -2
  175. package/dist/stored.d.ts +24 -13
  176. package/dist/stored.d.ts.map +1 -1
  177. package/dist/stored.js +73 -17
  178. package/dist/surface.d.ts +4 -3
  179. package/dist/surface.d.ts.map +1 -1
  180. package/dist/surface.js +12 -13
  181. package/dist/sync.d.ts.map +1 -1
  182. package/dist/sync.js +31 -17
  183. package/dist/tables.d.ts +14 -7
  184. package/dist/tables.d.ts.map +1 -1
  185. package/dist/tables.js +36 -15
  186. package/dist/tallies.d.ts.map +1 -1
  187. package/dist/tallies.js +1 -2
  188. package/dist/wire.d.ts +40 -3
  189. package/dist/wire.d.ts.map +1 -1
  190. package/dist/wire.js +11 -1
  191. package/package.json +3 -3
  192. package/dist/attempt.d.ts +0 -16
  193. package/dist/attempt.d.ts.map +0 -1
  194. package/dist/attempt.js +0 -70
  195. package/dist/job.d.ts +0 -5
  196. package/dist/job.d.ts.map +0 -1
  197. package/dist/job.js +0 -7
  198. package/dist/log.d.ts +0 -6
  199. package/dist/log.d.ts.map +0 -1
  200. package/dist/log.js +0 -14
@@ -0,0 +1,19 @@
1
+ import { queryKey } from '@agentshouse/mdmodel';
2
+ export const PAGE_METADATA_WORDS = {
3
+ heading: 'Page metadata',
4
+ app: 'App',
5
+ address: 'Address',
6
+ queries: 'Local Queries',
7
+ };
8
+ const PAGE_METADATA_QUERIES = 10;
9
+ export function pageMetadataBlock(app, address, queries) {
10
+ const held = [...new Set(queries.map(queryKey))];
11
+ return [
12
+ PAGE_METADATA_WORDS.heading,
13
+ `${PAGE_METADATA_WORDS.app}: ${app}`,
14
+ `${PAGE_METADATA_WORDS.address}: ${address}`,
15
+ ...(held.length === 0 || held.length > PAGE_METADATA_QUERIES
16
+ ? []
17
+ : [`${PAGE_METADATA_WORDS.queries}:`, ...held]),
18
+ ].join('\n');
19
+ }
package/dist/parts.d.ts CHANGED
@@ -1,11 +1,4 @@
1
- import { type Part, type SessionState } from '@agentshouse/session-content';
2
- export type ChatWork = {
3
- readonly kind: 'job' | 'schedule' | 'subagent';
4
- readonly title: string;
5
- readonly next: string | null;
6
- readonly activity: string | null;
7
- };
8
- export declare function counted(count: number): string;
1
+ import { type Part } from '@agentshouse/session-content';
2
+ export declare function currentStep(parts: readonly Part[]): string | null;
9
3
  export declare function runningLine(parts: readonly Part[]): string | null;
10
- export declare function workOf(state: SessionState | null): readonly ChatWork[];
11
4
  //# sourceMappingURL=parts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../src/parts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,IAAI,EAAE,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAGnF,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,MAAM,GAAG,IAAI,CAMjE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,QAAQ,EAAE,CAOtE"}
1
+ {"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../src/parts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAGhE,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,MAAM,GAAG,IAAI,CAGjE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,MAAM,GAAG,IAAI,CAKjE"}
package/dist/parts.js CHANGED
@@ -1,21 +1,13 @@
1
1
  import { isOwn } from '@agentshouse/session-content';
2
2
  import { excerpt } from './read.js';
3
- export function counted(count) {
4
- return count === 1 ? '1 command' : `${count} commands`;
3
+ export function currentStep(parts) {
4
+ const call = [...parts].reverse().find((part) => part.type === 'call');
5
+ return call?.type === 'call' && call.line !== '' ? call.line : null;
5
6
  }
6
7
  export function runningLine(parts) {
7
- const newest = parts.filter(isOwn).reverse();
8
- const note = newest.find((part) => part.type === 'text' && part.text.trim() !== '');
8
+ const own = parts.filter(isOwn);
9
+ const note = [...own].reverse().find((part) => part.type === 'text' && part.text.trim() !== '');
9
10
  if (note?.type === 'text')
10
11
  return excerpt(note.text);
11
- const call = newest.find((part) => part.type === 'call');
12
- return call?.type === 'call' && call.line !== '' ? call.line : null;
13
- }
14
- export function workOf(state) {
15
- return (state?.running ?? []).map(({ kind, label, progress, next }) => ({
16
- kind: kind === 'subagent' || kind === 'schedule' ? kind : 'job',
17
- title: label,
18
- next,
19
- activity: progress,
20
- }));
12
+ return currentStep(own);
21
13
  }
@@ -1,20 +1,41 @@
1
- import type { PlanReach } from './query.js';
1
+ import { type InstallShare } from './install.js';
2
+ import { type ReadinessChange } from './observation.js';
2
3
  import { type PortReach } from './reach.js';
3
- import { type CodeAvailability, type ConnectionAvailability, type Readiness } from './readiness.js';
4
+ import { type CodeAvailability, type ConnectionAvailability, type Readiness, type RoomCoverage } from './readiness.js';
4
5
  import type { Runtime } from './runtime.js';
5
6
  export type ReadinessPort = {
6
7
  readonly target: string;
7
8
  readonly code: CodeAvailability;
8
9
  };
10
+ export type ReadinessMessage = Readiness | ReadinessChange;
9
11
  export type ReadinessWatch = {
10
12
  readonly port: ReadinessPort;
11
13
  readonly reach: PortReach | null;
12
- readonly deliver: (readiness: Readiness) => void;
14
+ readonly deliver: (readiness: ReadinessMessage) => void;
15
+ };
16
+ type Share = InstallShare & {
17
+ readonly coverage: RoomCoverage;
18
+ };
19
+ type Totals = {
20
+ installing: number;
21
+ downloading: number;
22
+ acquiring: number;
23
+ unsettled: number;
24
+ done: number;
25
+ total: number;
26
+ };
27
+ export type ReadinessShowing = {
28
+ readonly listing: number;
29
+ readonly roomsListed: boolean;
30
+ readonly named: ReadonlySet<string> | null;
31
+ readonly rooms: Map<string, Share>;
32
+ readonly totals: Totals;
33
+ shown: string;
13
34
  };
14
35
  export declare function prepare(runtime: Runtime, locators?: readonly string[]): void;
15
- export declare function roomsOfReach(reach: PlanReach): ReadonlySet<string>;
16
36
  export declare function connectionNow(runtime: Runtime): Promise<ConnectionAvailability>;
17
- export declare function deliverOwedReadiness(runtime: Runtime, owed: readonly ReadinessWatch[]): Promise<void>;
18
- export declare function watchReadiness({ store }: Runtime, port: ReadinessPort, reach: PortReach | null, deliver: (readiness: Readiness) => void): () => void;
37
+ export declare function deliverOwedReadiness(runtime: Runtime, owed: readonly ReadinessWatch[], touched: ReadonlySet<string> | null): Promise<void>;
38
+ export declare function watchReadiness({ store }: Runtime, port: ReadinessPort, reach: PortReach | null, deliver: (readiness: ReadinessMessage) => void): () => void;
19
39
  export declare function filled(runtime: Runtime): void;
40
+ export {};
20
41
  //# sourceMappingURL=preparation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"preparation.d.ts","sourceRoot":"","sources":["../src/preparation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAE3B,KAAK,SAAS,EAEf,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;CAClD,CAAC;AAwCF,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,GAAE,SAAS,MAAM,EAAO,QA+BzE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAElE;AAgDD,wBAAsB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAMrF;AAoFD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,cAAc,EAAE,iBAI3F;AAED,wBAAgB,cAAc,CAC5B,EAAE,KAAK,EAAE,EAAE,OAAO,EAClB,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,SAAS,GAAG,IAAI,EACvB,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,GACtC,MAAM,IAAI,CAQZ;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,QAMtC"}
1
+ {"version":3,"file":"preparation.d.ts","sourceRoot":"","sources":["../src/preparation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE/E,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAE3B,KAAK,SAAS,EAEd,KAAK,YAAY,EAElB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,eAAe,CAAC;AAE3D,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACzD,CAAC;AAEF,KAAK,KAAK,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,CAAC;AAEhE,KAAK,MAAM,GAAG;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAwCF,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,GAAE,SAAS,MAAM,EAAO,QA4BzE;AAuDD,wBAAsB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAMrF;AAkMD,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,SAAS,cAAc,EAAE,EAC/B,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,iBAKpC;AAED,wBAAgB,cAAc,CAC5B,EAAE,KAAK,EAAE,EAAE,OAAO,EAClB,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,SAAS,GAAG,IAAI,EACvB,OAAO,EAAE,CAAC,SAAS,EAAE,gBAAgB,KAAK,IAAI,GAC7C,MAAM,IAAI,CAQZ;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,QAKtC"}
@@ -1,10 +1,11 @@
1
1
  import { changeSet } from './change-set.js';
2
2
  import { uncaught } from './failure.js';
3
- import { installationOf } from './install.js';
4
- import { listedLocators } from './listing.js';
3
+ import { installationOf, installShare } from './install.js';
4
+ import { listedLocators, listedOrHeld } from './listing.js';
5
+ import { keyedAt, keyedChange, unchanged, } from './observation.js';
5
6
  import { planReach } from './reach.js';
6
- import { readinessOf, } from './readiness.js';
7
- import { roomOfKey } from './rows.js';
7
+ import { COMPLETE_ROOMS, readinessOf, } from './readiness.js';
8
+ import { roomsOfReach } from './rows.js';
8
9
  import { recoverReads } from './shown.js';
9
10
  import { yielded } from './turn.js';
10
11
  async function prepareReplica(runtime, locator) {
@@ -23,8 +24,8 @@ async function prepareReplica(runtime, locator) {
23
24
  if ((await store.rooms([locator])).get(locator)?.record.key !== key)
24
25
  continue;
25
26
  store.changed(changeSet(locator, { documents: null }));
26
- recoverReads(runtime);
27
- store.readiness.queue();
27
+ recoverReads(runtime, [locator]);
28
+ store.readiness.queue([locator]);
28
29
  return;
29
30
  }
30
31
  }
@@ -33,14 +34,13 @@ async function unprepared({ store }) {
33
34
  const { unpreparedDemand, unpreparable } = store.device.now();
34
35
  return [...unpreparedDemand, ...held.keys()].find((locator) => !(held.get(locator)?.indexed ?? false) && !unpreparable.has(locator));
35
36
  }
36
- function unpreparedBy({ store, journal }, locator, error) {
37
+ function unpreparedBy({ store }, locator) {
37
38
  const { unpreparable } = store.device.now();
38
39
  store.device.set({ unpreparable: new Set([...unpreparable, locator]) });
39
- journal.record(`preparation failed ${locator} ${error instanceof Error ? error.name : 'unknown'}`);
40
- store.readiness.queue();
40
+ store.readiness.queue([locator]);
41
41
  }
42
42
  export function prepare(runtime, locators = []) {
43
- const { store, socket, journal } = runtime;
43
+ const { store, socket } = runtime;
44
44
  const { device } = store;
45
45
  if (locators.length > 0) {
46
46
  device.set({ unpreparedDemand: new Set([...device.now().unpreparedDemand, ...locators]) });
@@ -57,11 +57,10 @@ export function prepare(runtime, locators = []) {
57
57
  const demand = new Set(device.now().unpreparedDemand);
58
58
  demand.delete(waiting);
59
59
  device.set({ unpreparedDemand: demand });
60
- await prepareReplica(runtime, waiting).catch((error) => unpreparedBy(runtime, waiting, error));
60
+ await prepareReplica(runtime, waiting).catch(() => unpreparedBy(runtime, waiting));
61
61
  }
62
62
  }
63
63
  catch (error) {
64
- journal.record('preparation failed');
65
64
  uncaught(error);
66
65
  }
67
66
  finally {
@@ -69,19 +68,16 @@ export function prepare(runtime, locators = []) {
69
68
  }
70
69
  })();
71
70
  }
72
- export function roomsOfReach(reach) {
73
- return new Set([...reach.rooms, ...reach.documents.map(roomOfKey)]);
71
+ function requires(runtime, named, held, room) {
72
+ const listed = listedOrHeld(runtime, held, room);
73
+ if (named === null)
74
+ return listed;
75
+ return named.has(room) && (!runtime.socket.session.now().roomsListed || listed);
74
76
  }
75
- function requiredRooms(runtime, given, held) {
76
- const { roomsListed } = runtime.socket.session.now();
77
- const reach = planReach(given);
78
- const listed = new Set(listedLocators(runtime, held));
79
- if (reach === null)
80
- return { listed: roomsListed, rooms: [...listed].sort() };
81
- const named = [...roomsOfReach(reach)].sort();
82
- if (roomsListed)
83
- return { listed: true, rooms: named.filter((room) => listed.has(room)) };
84
- return { listed: named.every((room) => held.has(room)), rooms: named };
77
+ function requiredRooms(runtime, named, held) {
78
+ return [...(named ?? listedLocators(runtime, held))]
79
+ .filter((room) => requires(runtime, named, held, room))
80
+ .sort();
85
81
  }
86
82
  function roomState({ socket, presence }, locator, held) {
87
83
  if (socket.session.now().roomsListed &&
@@ -114,29 +110,89 @@ export async function connectionNow(runtime) {
114
110
  if (socket.isOpen() || socket.session.now().moving.providerUnreachable || socket.streamed) {
115
111
  return connectionOf(runtime, null);
116
112
  }
117
- return connectionOf(runtime, (await (await store.open()).facts()).lastCompleted);
113
+ return connectionOf(runtime, (await (await store.open()).facts(['lastCompleted'])).lastCompleted);
118
114
  }
119
115
  async function readinessHeld({ store }) {
120
116
  const local = await store.open();
121
- const [held, facts] = await Promise.all([store.covering(), local.facts()]);
117
+ const [held, facts] = await Promise.all([
118
+ store.covering(),
119
+ local.facts(['lastCompleted', 'targets']),
120
+ ]);
122
121
  return { held: held.rooms, facts };
123
122
  }
124
- function readinessFor(runtime, port, reach, { held, facts }) {
125
- const { store, socket, usableWhenHeld } = runtime;
126
- const required = requiredRooms(runtime, reach, held);
127
- const coverage = required.rooms.map((room) => ({ room, state: roomState(runtime, room, held) }));
128
- const { unpreparable } = store.device.now();
129
- const preparing = coverage
130
- .filter((room) => room.state === 'preparing' && !unpreparable.has(room.room))
131
- .map(({ room }) => room);
123
+ function shareOf(runtime, room, held) {
124
+ const coverage = Object.freeze({ room, state: roomState(runtime, room, held) });
125
+ return { ...installShare(runtime.store, coverage, held), coverage };
126
+ }
127
+ function sameState(was, now) {
128
+ return was.coverage.state === now.coverage.state;
129
+ }
130
+ function coverageOf(change) {
131
+ return {
132
+ ...change,
133
+ changed: change.changed.map(([room, share]) => [room, share.coverage]),
134
+ };
135
+ }
136
+ function counted(totals, share, sign) {
137
+ const { state } = share.coverage;
138
+ totals.installing += share.installing ? sign : 0;
139
+ totals.downloading += share.downloading ? sign : 0;
140
+ totals.acquiring += state === 'acquiring' ? sign : 0;
141
+ totals.unsettled += COMPLETE_ROOMS.has(state) ? 0 : sign;
142
+ totals.done += sign * share.bytes.done;
143
+ totals.total += sign * share.bytes.total;
144
+ }
145
+ function showingOf(runtime, reach, held) {
146
+ const planned = planReach(reach);
147
+ const named = planned === null ? null : roomsOfReach(planned);
148
+ const totals = { installing: 0, downloading: 0, acquiring: 0, unsettled: 0, done: 0, total: 0 };
149
+ const rooms = new Map();
150
+ for (const room of requiredRooms(runtime, named, held)) {
151
+ const share = shareOf(runtime, room, held);
152
+ rooms.set(room, share);
153
+ counted(totals, share, 1);
154
+ }
155
+ return {
156
+ listing: runtime.presence.listing(),
157
+ roomsListed: runtime.socket.session.now().roomsListed,
158
+ named,
159
+ rooms,
160
+ totals,
161
+ shown: '',
162
+ };
163
+ }
164
+ function moved(runtime, showing, held, touched) {
165
+ const at = new Map();
166
+ for (const room of touched) {
167
+ at.set(room, requires(runtime, showing.named, held, room) ? shareOf(runtime, room, held) : null);
168
+ }
169
+ const change = keyedAt(showing.rooms, at, sameState);
170
+ if (change === null || change.removed.length > 0)
171
+ return null;
172
+ for (const [room, share] of at) {
173
+ if (share === null)
174
+ continue;
175
+ counted(showing.totals, showing.rooms.get(room), -1);
176
+ counted(showing.totals, share, 1);
177
+ showing.rooms.set(room, share);
178
+ }
179
+ return change;
180
+ }
181
+ function preparingIn(runtime, showing, rooms) {
182
+ const { unpreparable } = runtime.store.device.now();
183
+ const preparing = [...rooms].filter((room) => showing.rooms.get(room)?.coverage.state === 'preparing' && !unpreparable.has(room));
132
184
  if (preparing.length > 0)
133
185
  prepare(runtime, preparing);
186
+ }
187
+ function shownOf(runtime, { port, reach }, { named, totals }, { facts }) {
188
+ const { store, socket, usableWhenHeld } = runtime;
134
189
  const { persistence, storageLoss, heldWhenOpened } = store.device.now();
190
+ const { roomsListed } = socket.session.now();
135
191
  return readinessOf({
136
192
  code: port.code,
137
193
  coverage: {
138
- listed: required.listed,
139
- rooms: coverage,
194
+ listed: named === null ? roomsListed : roomsListed || totals.acquiring === 0,
195
+ unsettled: totals.unsettled,
140
196
  conversations: conversationCoverage(runtime, reach),
141
197
  },
142
198
  persistence,
@@ -147,53 +203,79 @@ function readinessFor(runtime, port, reach, { held, facts }) {
147
203
  ? 'write-halted'
148
204
  : 'open',
149
205
  space: store.space.full() ? 'full' : null,
150
- installation: installationOf(store, coverage, held),
206
+ installation: installationOf(totals.installing, totals.downloading, {
207
+ done: totals.done,
208
+ total: totals.total,
209
+ }),
151
210
  lost: storageLoss !== null,
152
211
  established: facts.targets[port.target]?.established === true ||
153
212
  (heldWhenOpened && usableWhenHeld.includes(port.target)),
154
213
  });
155
214
  }
156
215
  function establish(runtime, name) {
157
- const { store, journal } = runtime;
216
+ const { store } = runtime;
158
217
  const { device } = store;
159
218
  if (device.now().establishing.has(name))
160
219
  return;
161
220
  device.set({ establishing: new Set([...device.now().establishing, name]) });
162
221
  void store
163
222
  .durably(async (local) => {
164
- const { targets } = await local.facts();
223
+ const { targets } = await local.facts(['targets']);
165
224
  await local.fact('targets', { ...targets, [name]: { established: true } });
166
225
  })
167
226
  .then(() => {
168
- store.readiness.queue();
227
+ store.readiness.queue([]);
169
228
  void probeEachMinute(runtime);
170
- }, (error) => {
171
- journal.record(`target record failed ${name}`);
172
- uncaught(error);
173
- })
229
+ }, uncaught)
174
230
  .finally(() => {
175
231
  const establishing = new Set(device.now().establishing);
176
232
  establishing.delete(name);
177
233
  device.set({ establishing });
178
234
  });
179
235
  }
180
- function deliverReadiness(runtime, watch, held) {
181
- if (!runtime.store.readiness.held(watch))
236
+ function deliverReadiness(runtime, watch, held, touched) {
237
+ const { readiness } = runtime.store;
238
+ if (!readiness.held(watch))
182
239
  return;
183
- const readiness = readinessFor(runtime, watch.port, watch.reach, held);
184
- if (readiness.ready && held.facts.targets[watch.port.target]?.established !== true) {
240
+ const kept = readiness.kept(watch);
241
+ const patched = kept === undefined ||
242
+ touched === null ||
243
+ kept.listing !== runtime.presence.listing() ||
244
+ kept.roomsListed !== runtime.socket.session.now().roomsListed
245
+ ? null
246
+ : moved(runtime, kept, held.held, touched);
247
+ const showing = patched === null ? showingOf(runtime, watch.reach, held.held) : kept;
248
+ preparingIn(runtime, showing, patched === null ? showing.rooms.keys() : touched);
249
+ const shown = shownOf(runtime, watch, showing, held);
250
+ if (shown.ready && held.facts.targets[watch.port.target]?.established !== true) {
185
251
  establish(runtime, watch.port.target);
186
252
  }
187
- if (!runtime.store.readiness.changed(watch, JSON.stringify(readiness)))
253
+ const text = JSON.stringify(shown);
254
+ const before = kept?.shown;
255
+ showing.shown = text;
256
+ readiness.keep(watch, showing);
257
+ if (kept === undefined) {
258
+ watch.deliver({
259
+ ...shown,
260
+ coverage: {
261
+ ...shown.coverage,
262
+ rooms: [...showing.rooms.values()].map(({ coverage }) => coverage),
263
+ },
264
+ });
188
265
  return;
189
- watch.deliver(structuredClone(readiness));
266
+ }
267
+ const rooms = coverageOf(patched ??
268
+ keyedChange(kept.rooms, [...showing.rooms.keys()], [...showing.rooms.values()], sameState));
269
+ if (text === before && unchanged(rooms))
270
+ return;
271
+ watch.deliver({ shown, rooms });
190
272
  }
191
- export async function deliverOwedReadiness(runtime, owed) {
273
+ export async function deliverOwedReadiness(runtime, owed, touched) {
192
274
  const held = await readinessHeld(runtime);
193
275
  if (runtime.socket.closed())
194
276
  return;
195
277
  for (const watch of owed)
196
- deliverReadiness(runtime, watch, held);
278
+ deliverReadiness(runtime, watch, held, touched);
197
279
  }
198
280
  export function watchReadiness({ store }, port, reach, deliver) {
199
281
  const watch = { port, reach, deliver };
@@ -202,17 +284,16 @@ export function watchReadiness({ store }, port, reach, deliver) {
202
284
  return stop;
203
285
  }
204
286
  export function filled(runtime) {
205
- const { store, socket, journal } = runtime;
287
+ const { store, socket } = runtime;
206
288
  if (socket.closed() || !store.space.fill())
207
289
  return;
208
- journal.record('space full');
209
- store.readiness.queue();
290
+ store.readiness.queue([]);
210
291
  void probeEachMinute(runtime);
211
292
  }
212
293
  async function installedTarget({ store }) {
213
294
  if (store.device.now().heldWhenOpened)
214
295
  return true;
215
- const { targets } = await (await store.open()).facts();
296
+ const { targets } = await (await store.open()).facts(['targets']);
216
297
  return Object.values(targets).some((target) => target.established);
217
298
  }
218
299
  async function probeEachMinute(runtime) {
@@ -9,6 +9,7 @@ type Standing = {
9
9
  readonly repairing: boolean;
10
10
  readonly reloadDue: boolean;
11
11
  };
12
+ export declare function lockingMode(mode: string | undefined): boolean;
12
13
  type Listing = {
13
14
  readonly whole: boolean;
14
15
  readonly live: boolean;
@@ -25,7 +26,10 @@ export type Presence = {
25
26
  modelled(locator: string, model: ModelState | null): void;
26
27
  installed(locator: string, bootstrapped: boolean): void;
27
28
  locked(locator: string, stored: () => Promise<string | null>): Promise<boolean>;
28
- lockedAmong(stored: ReadonlyMap<string, string>): readonly string[];
29
+ lockedAmong(stored: ReadonlyMap<string, {
30
+ readonly offline: string;
31
+ }>, locking: ReadonlySet<string>): readonly string[];
32
+ lockedAs(locator: string, mode: string | undefined): boolean;
29
33
  connectionLost(lapsed: () => void): void;
30
34
  connectionLive(): void;
31
35
  lapse(): void;
@@ -41,6 +45,8 @@ export type Presence = {
41
45
  writing(locator: string): boolean;
42
46
  unwritten(locator: string): void;
43
47
  lost(locator: string): boolean;
48
+ losing(): boolean;
49
+ listing(): number;
44
50
  losses(): number;
45
51
  lostSince(locator: string, losses: number): boolean;
46
52
  liftable(locator: string, discovery: number): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"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"}
package/dist/presence.js CHANGED
@@ -1,3 +1,6 @@
1
+ export function lockingMode(mode) {
2
+ return mode === 'locked';
3
+ }
1
4
  const UNANSWERED = {
2
5
  stale: false,
3
6
  repairable: null,
@@ -15,6 +18,8 @@ const NOT_READY_MS = [1_000, 2_000, 3_000, 5_000, 8_000, 11_000, 15_000];
15
18
  const LOCK_GRACE_MS = 120_000;
16
19
  export function createPresence() {
17
20
  const listed = new Map();
21
+ const lockable = new Set();
22
+ let listings = 0;
18
23
  const answered = new Map();
19
24
  const marks = new Map();
20
25
  const lastLost = new Map();
@@ -59,7 +64,7 @@ export function createPresence() {
59
64
  return true;
60
65
  }
61
66
  function locks(locator, mode) {
62
- return mode === 'locked' && !answer(locator).confirmed && !marks.has(locator);
67
+ return lockingMode(mode) && !answer(locator).confirmed && !marks.has(locator);
63
68
  }
64
69
  function liftable(locator, discovery) {
65
70
  const mark = marks.get(locator);
@@ -67,11 +72,18 @@ export function createPresence() {
67
72
  }
68
73
  return {
69
74
  list(found, { whole, live }) {
75
+ listings += 1;
70
76
  const kept = found.filter(({ locator }) => !marks.has(locator));
71
- if (whole)
77
+ if (whole) {
72
78
  listed.clear();
79
+ lockable.clear();
80
+ }
73
81
  for (const room of kept) {
74
82
  listed.set(room.locator, room);
83
+ if (lockingMode(room.replica.offline))
84
+ lockable.add(room.locator);
85
+ else
86
+ lockable.delete(room.locator);
75
87
  change(room.locator, {
76
88
  refusal: null,
77
89
  unreading: false,
@@ -125,13 +137,10 @@ export function createPresence() {
125
137
  return false;
126
138
  return locks(locator, (await stored()) ?? listed.get(locator)?.replica.offline);
127
139
  },
128
- lockedAmong(stored) {
129
- const modes = new Map([...listed].map(([locator, room]) => [locator, room.replica.offline]));
130
- for (const [locator, mode] of stored)
131
- modes.set(locator, mode);
132
- return [...modes]
133
- .filter(([locator, mode]) => locks(locator, mode))
134
- .map(([locator]) => locator)
140
+ lockedAs: locks,
141
+ lockedAmong(stored, locking) {
142
+ return [...new Set([...lockable, ...locking])]
143
+ .filter((locator) => locks(locator, stored.get(locator)?.offline ?? listed.get(locator)?.replica.offline))
135
144
  .sort();
136
145
  },
137
146
  connectionLost(lapsed) {
@@ -184,7 +193,9 @@ export function createPresence() {
184
193
  return false;
185
194
  marks.set(locator, { during, written: false });
186
195
  lastLost.set(locator, ++lossCount);
196
+ listings += 1;
187
197
  listed.delete(locator);
198
+ lockable.delete(locator);
188
199
  readied(locator);
189
200
  const { repairing, reloadDue } = answer(locator);
190
201
  answered.set(locator, { ...UNANSWERED, repairing, reloadDue });
@@ -203,6 +214,8 @@ export function createPresence() {
203
214
  marks.set(locator, { ...mark, written: false });
204
215
  },
205
216
  lost: (locator) => marks.has(locator),
217
+ losing: () => marks.size > 0,
218
+ listing: () => listings,
206
219
  losses: () => lossCount,
207
220
  lostSince: (locator, losses) => marks.has(locator) || (lastLost.get(locator) ?? 0) > losses,
208
221
  liftable,
package/dist/queries.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type FiguresCover } from './figures.js';
2
- import type { Cover, Ran } from './live.js';
2
+ import { type Cover, type Ran } from './live.js';
3
3
  import { type Plan, type QueryResult } from './query.js';
4
4
  import { type Deliver, type Fail, type PortReach } from './reach.js';
5
5
  import type { Runtime } from './runtime.js';
@@ -9,7 +9,7 @@ export declare function figuresCover(runtime: Runtime): Promise<FiguresCover>;
9
9
  export declare function answeredPlan(runtime: Runtime, plan: Plan, cover: () => Promise<Cover>): Promise<Ran>;
10
10
  export declare function rowsQuery(runtime: Runtime, plan: Plan): Promise<QueryResult>;
11
11
  export declare function planned(runtime: Runtime, input: unknown, reach: PortReach | null): Promise<Plan>;
12
- export declare function roomTallies(runtime: Runtime, rooms: readonly QueryRoom[], since: string): Promise<readonly import("./tallies.js").RoomTally[]>;
12
+ export declare function roomTallies(runtime: Runtime, rooms: readonly QueryRoom[], since: string): Promise<readonly import("./tallies.ts").RoomTally[]>;
13
13
  export declare function watchPlan(runtime: Runtime, plan: Plan, deliver: Deliver, fail: Fail): () => void;
14
14
  export declare function watchPlanned(runtime: Runtime, planning: Promise<Plan>, deliver: Deliver, fail: Fail): () => void;
15
15
  export declare function searched(runtime: Runtime, input: unknown, reach: PortReach | null): Promise<SearchResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAK5C,OAAO,EAIL,KAAK,IAAI,EACT,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAa,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAGhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAa,SAAS,EAAgB,MAAM,YAAY,CAAC;AAqFrE,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAa1E;AA2ED,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,GAC1B,OAAO,CAAC,GAAG,CAAC,CAQd;AAQD,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAWlF;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,wDAO7F;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,IAAI,CAchG;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,EACvB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,GACT,MAAM,IAAI,CAeZ;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,YAAY,CAAC,CAqDvB"}
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,EAAY,KAAK,KAAK,EAAE,KAAK,GAAG,EAAE,MAAM,WAAW,CAAC;AAK3D,OAAO,EAKL,KAAK,IAAI,EACT,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAa,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAGhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAa,SAAS,EAAgB,MAAM,YAAY,CAAC;AAiHrE,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAa1E;AAoGD,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,GAC1B,OAAO,CAAC,GAAG,CAAC,CAQd;AAQD,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAWlF;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,wDAO7F;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,IAAI,CAmBhG;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,EACvB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,GACT,MAAM,IAAI,CAeZ;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,YAAY,CAAC,CAkDvB"}