@opengeni/react 7.6.1 → 7.7.0-canary.37111190284001

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 (145) hide show
  1. package/README.md +47 -2
  2. package/dist/{browser-viewer-5X47I6T2.js → browser-viewer-63TXMINB.js} +6 -5
  3. package/dist/{chunk-5EXGU7UF.js → chunk-55DDDVKU.js} +3 -3
  4. package/dist/{chunk-UINDK6C3.js → chunk-7CYYXWHU.js} +5 -8
  5. package/dist/chunk-7CYYXWHU.js.map +1 -0
  6. package/dist/{chunk-LZ3KHA55.js → chunk-A2L5N3EI.js} +332 -339
  7. package/dist/chunk-A2L5N3EI.js.map +1 -0
  8. package/dist/{chunk-KGENSZKS.js → chunk-AAG4R3QN.js} +4 -3
  9. package/dist/chunk-AAG4R3QN.js.map +1 -0
  10. package/dist/{chunk-Z3DISEQN.js → chunk-CWWKTNKK.js} +35 -18
  11. package/dist/chunk-CWWKTNKK.js.map +1 -0
  12. package/dist/{chunk-WZ55DVGK.js → chunk-ELCE5SXV.js} +8 -4
  13. package/dist/chunk-ELCE5SXV.js.map +1 -0
  14. package/dist/{chunk-YSMMDOOE.js → chunk-GISEVGS6.js} +10 -2
  15. package/dist/chunk-GISEVGS6.js.map +1 -0
  16. package/dist/{chunk-BI57CQUV.js → chunk-I7IWRQLN.js} +2 -2
  17. package/dist/{chunk-XA6R7DJQ.js → chunk-IQUCRAT7.js} +3 -3
  18. package/dist/{chunk-CHPKSLPN.js → chunk-NBZ64YY7.js} +4 -2
  19. package/dist/chunk-NBZ64YY7.js.map +1 -0
  20. package/dist/{chunk-DV2DBNPQ.js → chunk-Q5QBEZIQ.js} +48 -29
  21. package/dist/chunk-Q5QBEZIQ.js.map +1 -0
  22. package/dist/{chunk-FGBCYQOT.js → chunk-RDKBXMWX.js} +120 -74
  23. package/dist/chunk-RDKBXMWX.js.map +1 -0
  24. package/dist/{chunk-45GE35O7.js → chunk-TKB4SB44.js} +10 -2
  25. package/dist/chunk-TKB4SB44.js.map +1 -0
  26. package/dist/{chunk-YCGBREUV.js → chunk-TOAH2BKA.js} +6 -2
  27. package/dist/{chunk-YCGBREUV.js.map → chunk-TOAH2BKA.js.map} +1 -1
  28. package/dist/chunk-UGLEYEMP.js +33 -0
  29. package/dist/chunk-UGLEYEMP.js.map +1 -0
  30. package/dist/{chunk-UJRYEWZI.js → chunk-UTRTG6LH.js} +48 -8
  31. package/dist/chunk-UTRTG6LH.js.map +1 -0
  32. package/dist/{chunk-YRYF2GLG.js → chunk-WYVLAAJA.js} +39 -31
  33. package/dist/chunk-WYVLAAJA.js.map +1 -0
  34. package/dist/{chunk-VGIKFIO2.js → chunk-XOAMRDDK.js} +6 -3
  35. package/dist/chunk-XOAMRDDK.js.map +1 -0
  36. package/dist/{chunk-6NEZPF53.js → chunk-YN7I3STW.js} +153 -32
  37. package/dist/chunk-YN7I3STW.js.map +1 -0
  38. package/dist/{chunk-KZ73RL76.js → chunk-YQEAA6LT.js} +7 -3
  39. package/dist/chunk-YQEAA6LT.js.map +1 -0
  40. package/dist/client.d.ts +4 -1
  41. package/dist/commands/types.d.ts +2 -0
  42. package/dist/components/approval-surface.d.ts +15 -0
  43. package/dist/components/session-conversation.d.ts +3 -0
  44. package/dist/composer.js +8 -7
  45. package/dist/{computer-viewer-7GF35SNY.js → computer-viewer-X2MBRZY4.js} +5 -4
  46. package/dist/connect.js +3 -3
  47. package/dist/hooks/use-browser-session.d.ts +4 -0
  48. package/dist/hooks/use-composer.d.ts +2 -0
  49. package/dist/hooks/use-computer-session.d.ts +2 -0
  50. package/dist/hooks/use-file-attachments.d.ts +2 -0
  51. package/dist/hooks/use-session-events.d.ts +1 -1
  52. package/dist/hooks/use-workspace-sessions.d.ts +15 -5
  53. package/dist/index.d.ts +2 -2
  54. package/dist/index.js +28 -21
  55. package/dist/index.js.map +1 -1
  56. package/dist/interaction.d.ts +1 -1
  57. package/dist/interaction.js +6 -5
  58. package/dist/interaction.js.map +1 -1
  59. package/dist/{latest-question-3BJGKQQ6.js → latest-question-CNEZ5KAN.js} +3 -3
  60. package/dist/lib/error-message.d.ts +7 -0
  61. package/dist/lib/format.d.ts +27 -3
  62. package/dist/lib/interaction-errors.d.ts +3 -0
  63. package/dist/machines.js +5 -4
  64. package/dist/{model-policy-picker-menu-PUTA5JOB.js → model-policy-picker-menu-GN2LTB7Z.js} +4 -4
  65. package/dist/model-policy.js +1 -1
  66. package/dist/provider.d.ts +5 -1
  67. package/dist/{queue-surface-implementation-2CAQAIHM.js → queue-surface-implementation-HENWYFWA.js} +3 -2
  68. package/dist/{queue-surface-implementation-2CAQAIHM.js.map → queue-surface-implementation-HENWYFWA.js.map} +1 -1
  69. package/dist/realtime.js +2 -2
  70. package/dist/{sandbox-files-AEJTWGT4.js → sandbox-files-BBC47SLD.js} +4 -3
  71. package/dist/session-ui.d.ts +1 -1
  72. package/dist/session-ui.js +13 -12
  73. package/dist/session-ui.js.map +1 -1
  74. package/dist/session.js +7 -6
  75. package/dist/usage.js +2 -1
  76. package/dist/usage.js.map +1 -1
  77. package/package.json +3 -3
  78. package/src/client.ts +5 -1
  79. package/src/commands/registry.ts +18 -15
  80. package/src/commands/types.ts +2 -0
  81. package/src/components/approval-surface.tsx +166 -42
  82. package/src/components/browser-viewer.tsx +38 -9
  83. package/src/components/composer.tsx +9 -2
  84. package/src/components/computer-viewer.tsx +160 -30
  85. package/src/components/generated-video-player.tsx +4 -2
  86. package/src/components/human-input-form.tsx +18 -5
  87. package/src/components/message-timeline.tsx +120 -168
  88. package/src/components/model-policy-picker.tsx +2 -15
  89. package/src/components/open-geni-chat.tsx +11 -4
  90. package/src/components/queue-surface-state.tsx +3 -1
  91. package/src/components/session-chrome.tsx +5 -2
  92. package/src/components/session-commands-panel.tsx +3 -1
  93. package/src/components/session-conversation.tsx +10 -3
  94. package/src/components/session-list.tsx +7 -5
  95. package/src/components/session-mcp-capability-card.tsx +11 -1
  96. package/src/hooks/internal.ts +3 -2
  97. package/src/hooks/use-browser-session.ts +115 -79
  98. package/src/hooks/use-composer.ts +70 -31
  99. package/src/hooks/use-computer-session.ts +57 -6
  100. package/src/hooks/use-file-attachments.ts +16 -3
  101. package/src/hooks/use-goal.ts +2 -1
  102. package/src/hooks/use-session-capabilities.ts +3 -2
  103. package/src/hooks/use-session-events.ts +15 -8
  104. package/src/hooks/use-slash-commands.ts +6 -11
  105. package/src/hooks/use-turn-queue.ts +2 -1
  106. package/src/hooks/use-workspace-sessions.ts +40 -7
  107. package/src/index.ts +7 -2
  108. package/src/interaction.ts +1 -0
  109. package/src/lib/error-message.ts +37 -0
  110. package/src/lib/format.ts +73 -9
  111. package/src/lib/interaction-errors.ts +15 -0
  112. package/src/model-policy.ts +6 -1
  113. package/src/provider.tsx +12 -4
  114. package/src/session-ui.ts +1 -1
  115. package/src/timeline/projection.ts +12 -1
  116. package/styles/compiled.css +14 -30
  117. package/dist/chunk-45GE35O7.js.map +0 -1
  118. package/dist/chunk-6NEZPF53.js.map +0 -1
  119. package/dist/chunk-CHPKSLPN.js.map +0 -1
  120. package/dist/chunk-DV2DBNPQ.js.map +0 -1
  121. package/dist/chunk-FGBCYQOT.js.map +0 -1
  122. package/dist/chunk-KGENSZKS.js.map +0 -1
  123. package/dist/chunk-KZ73RL76.js.map +0 -1
  124. package/dist/chunk-LZ3KHA55.js.map +0 -1
  125. package/dist/chunk-UINDK6C3.js.map +0 -1
  126. package/dist/chunk-UJRYEWZI.js.map +0 -1
  127. package/dist/chunk-VGIKFIO2.js.map +0 -1
  128. package/dist/chunk-WZ55DVGK.js.map +0 -1
  129. package/dist/chunk-YRYF2GLG.js.map +0 -1
  130. package/dist/chunk-YSMMDOOE.js.map +0 -1
  131. package/dist/chunk-Z3DISEQN.js.map +0 -1
  132. package/dist/components/timeline-pill-geometry.d.ts +0 -8
  133. package/dist/components/timeline-pill-placement.d.ts +0 -24
  134. package/dist/timeline-pill-geometry-Z23V243M.js +0 -110
  135. package/dist/timeline-pill-geometry-Z23V243M.js.map +0 -1
  136. package/src/components/timeline-pill-geometry.ts +0 -169
  137. package/src/components/timeline-pill-placement.ts +0 -99
  138. /package/dist/{browser-viewer-5X47I6T2.js.map → browser-viewer-63TXMINB.js.map} +0 -0
  139. /package/dist/{chunk-5EXGU7UF.js.map → chunk-55DDDVKU.js.map} +0 -0
  140. /package/dist/{chunk-BI57CQUV.js.map → chunk-I7IWRQLN.js.map} +0 -0
  141. /package/dist/{chunk-XA6R7DJQ.js.map → chunk-IQUCRAT7.js.map} +0 -0
  142. /package/dist/{computer-viewer-7GF35SNY.js.map → computer-viewer-X2MBRZY4.js.map} +0 -0
  143. /package/dist/{latest-question-3BJGKQQ6.js.map → latest-question-CNEZ5KAN.js.map} +0 -0
  144. /package/dist/{model-policy-picker-menu-PUTA5JOB.js.map → model-policy-picker-menu-GN2LTB7Z.js.map} +0 -0
  145. /package/dist/{sandbox-files-AEJTWGT4.js.map → sandbox-files-BBC47SLD.js.map} +0 -0
@@ -2,14 +2,18 @@ import {
2
2
  buildTimeline,
3
3
  groupTimeline,
4
4
  sessionStatusFromEvents
5
- } from "./chunk-KGENSZKS.js";
5
+ } from "./chunk-AAG4R3QN.js";
6
6
  import {
7
7
  useDebouncedCallback,
8
8
  useMutationRunner,
9
9
  usePageLiveActivity,
10
10
  usePolledValue,
11
11
  useSessionEventTrigger
12
- } from "./chunk-KZ73RL76.js";
12
+ } from "./chunk-YQEAA6LT.js";
13
+ import {
14
+ normalizeError,
15
+ useErrorMessage
16
+ } from "./chunk-UGLEYEMP.js";
13
17
  import {
14
18
  useEmbeddedFileAttachments,
15
19
  useEmbeddedHumanInputSession,
@@ -127,8 +131,8 @@ var FOREGROUND_COMPACT_CATCHUP_MAX_GROUPS = 16;
127
131
  var FOREGROUND_COMPACT_CATCHUP_MAX_BYTES = 512 * 1024;
128
132
  var EMPTY_EVENTS = [];
129
133
  var encoder = new TextEncoder();
130
- var SESSION_EVENT_BROWSER_MAX_BYTES = 160 * 1024 * 1024;
131
- var SESSION_EVENT_BROWSER_MAX_COUNT = 2e5;
134
+ var SESSION_EVENT_BROWSER_MAX_BYTES = 16 * 1024 * 1024;
135
+ var SESSION_EVENT_BROWSER_MAX_COUNT = 2e4;
132
136
  var SESSION_EVENT_BROWSER_PENDING_MAX_BYTES = 1024 * 1024;
133
137
  var SESSION_EVENT_BROWSER_PENDING_MAX_COUNT = 256;
134
138
  var EMPTY_EVENT_WINDOW = {
@@ -410,7 +414,7 @@ function useSessionEvents(sessionId, options = {}) {
410
414
  onOpen: () => {
411
415
  void Promise.resolve().then(() => reconcileSession(sessionId)).catch((cause) => {
412
416
  if (isCurrent()) {
413
- setError(cause instanceof Error ? cause : new Error(String(cause)));
417
+ setError(normalizeError(cause));
414
418
  }
415
419
  });
416
420
  },
@@ -443,7 +447,7 @@ function useSessionEvents(sessionId, options = {}) {
443
447
  } catch (cause) {
444
448
  if (isCurrent()) {
445
449
  flush();
446
- setError(cause instanceof Error ? cause : new Error(String(cause)));
450
+ setError(normalizeError(cause));
447
451
  setConnectionState("error");
448
452
  setInitialLoading(false);
449
453
  }
@@ -739,7 +743,7 @@ function useSessionEvents(sessionId, options = {}) {
739
743
  if (!isCurrent()) {
740
744
  return false;
741
745
  }
742
- setNewerError(reason instanceof Error ? reason : new Error(String(reason)));
746
+ setNewerError(normalizeError(reason));
743
747
  throw reason;
744
748
  } finally {
745
749
  if (!published && isCurrent()) {
@@ -830,7 +834,7 @@ function useSessionEvents(sessionId, options = {}) {
830
834
  let generation = navigationGenerationRef.current;
831
835
  const current = () => ownsNavigation() && generation === navigationGenerationRef.current;
832
836
  try {
833
- const { resolveLatestQuestion } = await import("./latest-question-3BJGKQQ6.js");
837
+ const { resolveLatestQuestion } = await import("./latest-question-CNEZ5KAN.js");
834
838
  if (!current()) return null;
835
839
  const destination = await resolveLatestQuestion({
836
840
  client,
@@ -910,10 +914,13 @@ function useSessionEvents(sessionId, options = {}) {
910
914
  const visibleEvents = identityMatches ? eventWindow.events : EMPTY_EVENTS;
911
915
  const timeline = useMemo(() => {
912
916
  const witness = questionEvidence?.client === client && questionEvidence.streamKey === streamKey && visibleEvents.some((event) => event.sequence === questionEvidence.anchor) ? questionEvidence.events : EMPTY_EVENTS;
917
+ const timelineOptions = { partialStart: hasOlder || eventWindow.truncated || after > 0 };
918
+ if (witness.length === 0) return buildTimeline(visibleEvents, timelineOptions);
913
919
  const ids = new Set(visibleEvents.map((event) => event.id));
914
- return buildTimeline([...visibleEvents, ...witness.filter((event) => !ids.has(event.id))], {
915
- partialStart: hasOlder || eventWindow.truncated || after > 0
916
- });
920
+ return buildTimeline(
921
+ [...visibleEvents, ...witness.filter((event) => !ids.has(event.id))],
922
+ timelineOptions
923
+ );
917
924
  }, [visibleEvents, hasOlder, eventWindow.truncated, after, questionEvidence, client, streamKey]);
918
925
  return {
919
926
  events: visibleEvents,
@@ -1707,7 +1714,7 @@ function operationKey() {
1707
1714
  return globalThis.crypto.randomUUID();
1708
1715
  }
1709
1716
  function asError(cause) {
1710
- return cause instanceof Error ? cause : new Error(String(cause));
1717
+ return normalizeError(cause);
1711
1718
  }
1712
1719
  function isOutcomeUnknownError(cause) {
1713
1720
  return typeof cause === "object" && cause !== null && cause.outcomeUnknown === true;
@@ -1819,6 +1826,7 @@ function secureContextRequiredErrorCode(error) {
1819
1826
  }
1820
1827
  function useFileAttachments(options = {}) {
1821
1828
  const { client, workspaceId } = useEmbeddedFileAttachments(options);
1829
+ const formatError = useErrorMessage();
1822
1830
  const pasteFilter = options.pasteFilter ?? isImage;
1823
1831
  const [attachments, setAttachments] = useState5([]);
1824
1832
  const attachmentsRef = useRef5(attachments);
@@ -1908,7 +1916,8 @@ function useFileAttachments(options = {}) {
1908
1916
  contentType: asset.contentType,
1909
1917
  sizeBytes: asset.sizeBytes,
1910
1918
  errorCode: void 0,
1911
- error: void 0
1919
+ error: void 0,
1920
+ errorCause: void 0
1912
1921
  } : attachment
1913
1922
  )
1914
1923
  );
@@ -1920,13 +1929,14 @@ function useFileAttachments(options = {}) {
1920
1929
  ...attachment,
1921
1930
  status: "failed",
1922
1931
  errorCode: secureContextRequiredErrorCode(error),
1923
- error: error instanceof Error ? error.message : String(error)
1932
+ error: formatError(error),
1933
+ errorCause: error
1924
1934
  } : attachment
1925
1935
  )
1926
1936
  );
1927
1937
  });
1928
1938
  },
1929
- [client, workspaceId, options.scope]
1939
+ [client, workspaceId, options.scope, formatError]
1930
1940
  );
1931
1941
  const addFiles = useCallback5(
1932
1942
  (files) => {
@@ -1959,7 +1969,13 @@ function useFileAttachments(options = {}) {
1959
1969
  }
1960
1970
  setAttachments(
1961
1971
  (current) => current.map(
1962
- (attachment) => attachment.id === id ? { ...attachment, status: "uploading", errorCode: void 0, error: void 0 } : attachment
1972
+ (attachment) => attachment.id === id ? {
1973
+ ...attachment,
1974
+ status: "uploading",
1975
+ errorCode: void 0,
1976
+ error: void 0,
1977
+ errorCause: void 0
1978
+ } : attachment
1963
1979
  )
1964
1980
  );
1965
1981
  startUpload(id, file);
@@ -2004,7 +2020,8 @@ function useFileAttachments(options = {}) {
2004
2020
  status: "ready",
2005
2021
  file,
2006
2022
  errorCode: void 0,
2007
- error: void 0
2023
+ error: void 0,
2024
+ errorCause: void 0
2008
2025
  } : {
2009
2026
  id: `restored:${file.id}`,
2010
2027
  name: file.filename,
@@ -2309,4 +2326,4 @@ export {
2309
2326
  projectPendingApprovals,
2310
2327
  conversationTimeline
2311
2328
  };
2312
- //# sourceMappingURL=chunk-Z3DISEQN.js.map
2329
+ //# sourceMappingURL=chunk-CWWKTNKK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/human-input.ts","../src/older-history.ts","../src/hooks/use-session-events.ts","../src/hooks/use-session.ts","../src/hooks/use-turn-queue.ts","../src/hooks/use-human-input.ts","../src/hooks/use-file-attachments.ts","../src/hooks/use-session-control.ts","../src/approvals.ts","../src/conversation-timeline.ts"],"sourcesContent":["import type { HumanInputQuestion, SessionEvent, SessionHumanInputRequest } from \"@opengeni/sdk\";\n\n/** Minimal actionable request shape available from the durable event log. */\nexport type PendingHumanInputRequest = {\n id: string;\n turnId: string | null;\n questions: HumanInputQuestion[];\n allowSkip: boolean;\n expiresAt: string | null;\n};\n\n/** A pending row stops being actionable at its durable deadline, even before refresh. */\nexport function isActionableHumanInputRequest(\n request: Pick<SessionHumanInputRequest, \"status\" | \"expiresAt\">,\n nowMs = Date.now(),\n): boolean {\n if (request.status !== \"pending\") return false;\n if (!request.expiresAt) return true;\n const deadline = Date.parse(request.expiresAt);\n return Number.isFinite(deadline) && deadline > nowMs;\n}\n\n/** Parse one generic `session.humanInput.requested` event defensively. */\nexport function humanInputRequestFromEvent(\n event: Pick<SessionEvent, \"type\" | \"payload\" | \"turnId\">,\n): PendingHumanInputRequest | null {\n if (event.type !== \"session.humanInput.requested\" || !isRecord(event.payload)) return null;\n const request = event.payload.request;\n if (!isRecord(request) || typeof request.id !== \"string\" || !Array.isArray(request.questions)) {\n return null;\n }\n return {\n id: request.id,\n turnId: event.turnId ?? null,\n questions: request.questions as HumanInputQuestion[],\n allowSkip: request.allowSkip === true,\n expiresAt: typeof request.expiresAt === \"string\" ? request.expiresAt : null,\n };\n}\n\n/**\n * Fold a durable event log into the structured requests that are actionable\n * now. Responses remove one request; a terminal owning turn clears any\n * unresolved requests that died with it. Replaying history cannot resurrect a\n * previously answered card.\n */\nexport function projectPendingHumanInputRequests(\n events: SessionEvent[],\n): PendingHumanInputRequest[] {\n const pending = new Map<string, PendingHumanInputRequest>();\n for (const event of events) {\n const requested = humanInputRequestFromEvent(event);\n if (requested) {\n pending.set(requested.id, requested);\n continue;\n }\n if (event.type === \"user.humanInputResponse\" && isRecord(event.payload)) {\n if (typeof event.payload.requestId === \"string\") pending.delete(event.payload.requestId);\n continue;\n }\n if (\n event.type === \"turn.completed\" ||\n event.type === \"turn.failed\" ||\n event.type === \"turn.cancelled\"\n ) {\n for (const [id, request] of pending) {\n if (\n request.turnId === null ||\n event.turnId === null ||\n event.turnId === undefined ||\n request.turnId === event.turnId\n ) {\n pending.delete(id);\n }\n }\n }\n }\n return [...pending.values()];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n","/**\n * Await-compatible older-history result with a causal commit receipt.\n *\n * `committed` flips synchronously before the accepted older window is exposed\n * to React. Returning this exact object preserves the receipt directly;\n * synchronous wrappers that discard it remain supported through receipt\n * capture, while replacing it asynchronously with a plain promise does not.\n */\nexport type OlderHistoryLoadReceipt = Promise<boolean> & {\n readonly committed: boolean;\n readonly tailPreserved?: boolean;\n};\n\n/**\n * Source-compatible public callback accepted by MessageTimeline.\n *\n * The callback historically returned `void`, which permits consumers to\n * return any synchronous value or promise. Receipt-aware loaders opt into the\n * stronger runtime contract by returning (or synchronously creating through a\n * wrapper) an {@link OlderHistoryLoadReceipt}.\n */\nexport type OlderHistoryLoader = () => unknown;\n\ntype MutableOlderHistoryLoadReceipt = Promise<boolean> & {\n committed: boolean;\n tailPreserved: boolean;\n};\n\ntype OlderHistoryReceiptCapture = (receipt: OlderHistoryLoadReceipt) => void;\n\nlet activeReceiptCapture: OlderHistoryReceiptCapture | undefined;\nlet preserveTailForAutomaticLoad = false;\n\n/** Bind a receipt before a synchronous forwarding stack can publish state. */\nexport function invokeOlderHistoryLoaderWithReceiptCapture(\n load: OlderHistoryLoader,\n capture: OlderHistoryReceiptCapture,\n preserveTail = false,\n): unknown {\n const previousCapture = activeReceiptCapture;\n const previousPreserveTail = preserveTailForAutomaticLoad;\n activeReceiptCapture = capture;\n preserveTailForAutomaticLoad = preserveTail;\n try {\n return load();\n } finally {\n activeReceiptCapture = previousCapture;\n preserveTailForAutomaticLoad = previousPreserveTail;\n }\n}\n\n/**\n * Build an await-compatible older-history receipt for custom timeline hosts.\n * Call `markCommitted` immediately before publishing an accepted older window.\n */\nexport function createOlderHistoryLoadReceipt(\n load: (\n markCommitted: () => void,\n preserveTail: boolean,\n markTailPreserved: () => void,\n ) => boolean | Promise<boolean>,\n): OlderHistoryLoadReceipt {\n let resolveResult!: (value: boolean | PromiseLike<boolean>) => void;\n let rejectResult!: (reason?: unknown) => void;\n const result = new Promise<boolean>((resolve, reject) => {\n resolveResult = resolve;\n rejectResult = reject;\n }) as MutableOlderHistoryLoadReceipt;\n result.committed = false;\n result.tailPreserved = false;\n activeReceiptCapture?.(result);\n try {\n const loaded = load(\n () => {\n result.committed = true;\n },\n preserveTailForAutomaticLoad,\n () => {\n result.tailPreserved = true;\n },\n );\n Promise.resolve(loaded).then(resolveResult, rejectResult);\n } catch (error) {\n rejectResult(error);\n }\n return result;\n}\n","import {\n sessionEventStreamCoveredThrough,\n type SessionEvent,\n type SessionStatus,\n type StreamConnectionState,\n} from \"@opengeni/sdk\";\nimport { startTransition, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useEmbeddedSession, type EmbeddedSessionClientOverride } from \"../session-context\";\nimport { createOlderHistoryLoadReceipt, type OlderHistoryLoadReceipt } from \"../older-history\";\nimport { buildTimeline, groupTimeline, sessionStatusFromEvents } from \"../timeline/projection\";\nimport type { TimelineItem } from \"../timeline/types\";\nimport type { EmbeddedSessionClientLike } from \"../client\";\nimport { normalizeError } from \"../lib/error-message\";\nimport { usePageLiveActivity } from \"./internal\";\nimport type { LatestQuestionOptions } from \"./latest-question\";\n\nexport type SessionEventsConnectionState = StreamConnectionState | \"idle\" | \"ended\" | \"error\";\n\nexport type UseSessionEventsOptions = EmbeddedSessionClientOverride & {\n /** Resume after this sequence (exclusive). Nonzero keeps full replay/resume semantics. */\n after?: number | undefined;\n /** Load a bounded tail by default, or opt back into full replay from `after`. */\n replay?: \"windowed\" | \"full\" | undefined;\n /** Pause the stream without unmounting (e.g. hidden tab). Defaults to true. */\n enabled?: boolean | undefined;\n};\n\nexport type UseSessionEventsResult = {\n /** Replayed + live events, ordered by sequence, no gaps, no duplicates. */\n events: SessionEvent[];\n /** Renderable timeline, including the bounded navigation witness for a distant queued prompt. */\n timeline: TimelineItem[];\n /** Latest session status observed in the event log, if any. */\n sessionStatus: SessionStatus | null;\n /** Sequence of the retained status projection, including events evicted from the window. */\n sessionStatusSequence?: number;\n connectionState: SessionEventsConnectionState;\n /** Highest sequence seen so far (0 before the first event). */\n lastSequence: number;\n /** Exact serialized bytes retained in the current browser event window. */\n windowBytes: number;\n /** Whether older delivered events were evicted from the browser window. */\n windowTruncated: boolean;\n /** True until the initial tail window has been applied (windowed mode). */\n initialLoading: boolean;\n /** A history window (including an empty tail) succeeded for this session/replay\n * identity. Stays true through later stream errors and navigation/reloads.\n * Full replay has no snapshot-completion watermark and does not set this by itself. */\n initialHistoryReady: boolean;\n /** Whether older durable events are available before the current window. */\n hasOlder: boolean;\n /** True while an older window is being fetched. */\n loadingOlder: boolean;\n /** Prepend an older density-bounded window; resolves true when more remain. */\n loadOlder: () => OlderHistoryLoadReceipt;\n /**\n * Durable events exist after the current window (history view jumped away\n * from the live tip, or a forward page is incomplete).\n */\n hasNewer: boolean;\n /** True while a newer history page is being fetched. */\n loadingNewer: boolean;\n /**\n * Append one density-bounded newer page without pulling the whole gap.\n * Resolves true when more newer history remains.\n */\n loadNewer: () => Promise<boolean>;\n /** True while replacing the window with the session start. */\n loadingOldest: boolean;\n /**\n * Jump to the durable session start: one bounded oldest window, no middle.\n * Leaves live streaming until {@link jumpToLatest} (or loadNewer catches up).\n */\n loadOldest: () => Promise<boolean>;\n /** True while reloading the live tip window. */\n loadingLatest: boolean;\n /**\n * Reload the newest bounded tip and resume live streaming. Use for\n * \"Jump to latest\" when the tip is not in memory (history view).\n */\n jumpToLatest: () => Promise<void>;\n /** Resolve the newest eligible durable human question. Pending prompts use the\n * optional queue destination and return null; started prompts load their actual\n * turn context (pass `timeline` to MessageTimeline as `items`). */\n jumpToLatestQuestion: (options?: LatestQuestionOptions) => Promise<number | null>;\n /** Replace history with a bounded window containing this exact durable event. */\n jumpToSequence: (sequence: number, options?: { signal?: AbortSignal }) => Promise<boolean>;\n loadingTarget: boolean;\n error: Error | null;\n};\n\n// Keep every browser history read inside one database batch, including the\n// server's one-row continuation lookahead. A large total session must never\n// turn one lazy page into dozens of sequential database round trips.\nconst SESSION_HISTORY_PAGE_SIZE = 1000;\nconst INITIAL_FETCH_CAP = 1;\nconst OLDER_GROUP_TARGET = 32;\nconst OLDER_FETCH_CAP = 2;\nconst NEWER_GROUP_TARGET = 32;\nconst NEWER_FETCH_CAP = 2;\nconst OLDEST_GROUP_TARGET = 32;\nconst OLDEST_FETCH_CAP = 2;\n// A tail page may land inside one unusually dense turn. Permit exactly one\n// additional bounded page to find its user/session boundary without turning a\n// fresh open into an unbounded history walk.\nconst BOUNDARY_PAGE_CAP = 1;\n// Foreground reconciliation is intentionally semantic, not merely time-based:\n// tiny raw gaps can stay on SSE; medium raw gaps get one compact probe so a\n// token-heavy single answer is not mistaken for hundreds of visible messages;\n// only a large/complex missed window reloads the latest tail.\nconst FOREGROUND_DIRECT_REPLAY_MAX_SEQUENCES = 16;\nconst FOREGROUND_COMPACT_PROBE_MAX_SEQUENCES = SESSION_HISTORY_PAGE_SIZE;\nconst FOREGROUND_COMPACT_CATCHUP_MAX_EVENTS = 128;\nconst FOREGROUND_COMPACT_CATCHUP_MAX_GROUPS = 16;\nconst FOREGROUND_COMPACT_CATCHUP_MAX_BYTES = 512 * 1024;\nconst EMPTY_EVENTS: SessionEvent[] = [];\nconst encoder = new TextEncoder();\n// Durable history remains on the server and is available through bounded\n// navigation. Keep the live browser working set small across multiple tabs;\n// serialized payloads also expand into objects and timeline projections.\nexport const SESSION_EVENT_BROWSER_MAX_BYTES = 16 * 1024 * 1024;\nexport const SESSION_EVENT_BROWSER_MAX_COUNT = 20_000;\nexport const SESSION_EVENT_BROWSER_PENDING_MAX_BYTES = 1024 * 1024;\nexport const SESSION_EVENT_BROWSER_PENDING_MAX_COUNT = 256;\n\nexport type BrowserSessionEventWindow = {\n events: SessionEvent[];\n bytes: number;\n truncated: boolean;\n};\n\nconst EMPTY_EVENT_WINDOW: BrowserSessionEventWindow = {\n events: EMPTY_EVENTS,\n bytes: 2,\n truncated: false,\n};\n\n/**\n * Live-stream a session's event log with replay-by-sequence, reconnect, and\n * batched React updates. Fresh loads default to a bounded tail window; pass\n * `replay: \"full\"` or a nonzero `after` for the previous full replay path.\n */\nexport function useSessionEvents(\n sessionId: string | null | undefined,\n options: UseSessionEventsOptions = {},\n): UseSessionEventsResult {\n const { client, workspaceId, reconcileSession } = useEmbeddedSession(options);\n const enabled = options.enabled ?? true;\n const pageLive = usePageLiveActivity();\n const streamEnabled = enabled && pageLive;\n const after = options.after ?? 0;\n const replay = options.replay ?? \"windowed\";\n const fullReplay = replay === \"full\" || after !== 0;\n const streamKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${after}\\u0000${fullReplay ? \"full\" : \"windowed\"}`;\n // Bind callbacks to this read lifetime, including a return to a previous\n // identity. Publish during render so old callbacks are fenced before passive\n // cleanup can advance the navigation generation.\n const navigationIdentityRef = useRef({ client, streamKey, enabled });\n if (\n navigationIdentityRef.current.client !== client ||\n navigationIdentityRef.current.streamKey !== streamKey ||\n navigationIdentityRef.current.enabled !== enabled\n ) {\n navigationIdentityRef.current = { client, streamKey, enabled };\n }\n const navigationIdentity = navigationIdentityRef.current;\n const ownsNavigation = useCallback(\n () => navigationIdentityRef.current === navigationIdentity,\n [navigationIdentity],\n );\n\n const [eventWindow, setEventWindow] = useState<BrowserSessionEventWindow>(EMPTY_EVENT_WINDOW);\n // One navigation witness, not a second history cache. Raw events stay contiguous.\n const [questionEvidence, setQuestionEvidence] = useState<{\n client: EmbeddedSessionClientLike;\n streamKey: string;\n anchor: number;\n events: SessionEvent[];\n } | null>(null);\n const [connectionState, setConnectionState] = useState<SessionEventsConnectionState>(\"idle\");\n const [error, setError] = useState<Error | null>(null);\n const [newerError, setNewerError] = useState<Error | null>(null);\n const [hasOlder, setHasOlder] = useState(false);\n const [hasNewer, setHasNewer] = useState(false);\n const [sessionStatusProjection, setSessionStatusProjection] = useState<SessionStatus | null>(\n null,\n );\n const [initialLoading, setInitialLoading] = useState(true);\n const [initialHistoryReady, setInitialHistoryReady] = useState(false);\n const [loadingOlder, setLoadingOlder] = useState(false);\n const [loadingNewer, setLoadingNewer] = useState(false);\n const [loadingOldest, setLoadingOldest] = useState(false);\n const [loadingLatest, setLoadingLatest] = useState(false);\n const [loadingTarget, setLoadingTarget] = useState(false);\n const loadingTargetRef = useRef(false);\n const [streamEpoch, setStreamEpoch] = useState(0);\n // \"history\" = reading a non-tip window; live SSE must not fill the gap.\n const [viewMode, setViewMode] = useState<\"live\" | \"history\">(\"live\");\n const lastSequenceRef = useRef(after);\n const streamResumeSequenceRef = useRef(after);\n const oldestSequenceRef = useRef<number | null>(null);\n const newestSequenceRef = useRef<number | null>(null);\n const hasOlderRef = useRef(false);\n const hasNewerRef = useRef(false);\n const loadingOlderRef = useRef(false);\n const loadingNewerRef = useRef(false);\n const loadingOldestRef = useRef(false);\n const loadingLatestRef = useRef(false);\n const viewModeRef = useRef<\"live\" | \"history\">(\"live\");\n const initialWindowLoadedRef = useRef(false);\n const reconcileAfterPageResumeRef = useRef(false);\n const streamAbortRef = useRef<AbortController | null>(null);\n const streamKeyRef = useRef<string | null>(null);\n const generationRef = useRef(0);\n const navigationGenerationRef = useRef(0);\n const eventWindowRef = useRef<BrowserSessionEventWindow>(EMPTY_EVENT_WINDOW);\n const sessionStatusRef = useRef<{\n sequence: number;\n status: SessionStatus | null;\n }>({\n sequence: after,\n status: null,\n });\n // Effects reset state after commit. Tag the state so the first render for a\n // new stream identity cannot expose the previous session's event log.\n const [stateStreamKey, setStateStreamKey] = useState(streamKey);\n\n // Reopening SSE after a prepend must not cancel the next history page.\n // Navigation belongs to the session/client lifetime, not the transport.\n useEffect(() => {\n navigationGenerationRef.current += 1;\n setNewerError(null);\n loadingOlderRef.current = false;\n loadingNewerRef.current = false;\n loadingOldestRef.current = false;\n loadingTargetRef.current = false;\n setQuestionEvidence(null);\n setLoadingTarget(false);\n setLoadingOlder(false);\n setLoadingNewer(false);\n setLoadingOldest(false);\n return () => {\n navigationGenerationRef.current += 1;\n };\n }, [client, workspaceId, sessionId, after, enabled, fullReplay]);\n\n useEffect(() => {\n // Reset the accumulated log only when the stream identity changes —\n // pausing via `enabled: false` keeps the timeline visible.\n if (streamKeyRef.current !== streamKey) {\n streamKeyRef.current = streamKey;\n setStateStreamKey(streamKey);\n eventWindowRef.current = EMPTY_EVENT_WINDOW;\n setEventWindow(EMPTY_EVENT_WINDOW);\n setError(null);\n setHasOlder(false);\n setHasNewer(false);\n sessionStatusRef.current = { sequence: after, status: null };\n setSessionStatusProjection(null);\n setLoadingOlder(false);\n setLoadingNewer(false);\n setLoadingOldest(false);\n setLoadingLatest(false);\n setInitialLoading(true);\n setInitialHistoryReady(false);\n lastSequenceRef.current = after;\n streamResumeSequenceRef.current = after;\n oldestSequenceRef.current = null;\n newestSequenceRef.current = null;\n hasOlderRef.current = false;\n hasNewerRef.current = false;\n loadingOlderRef.current = false;\n loadingNewerRef.current = false;\n loadingOldestRef.current = false;\n loadingLatestRef.current = false;\n viewModeRef.current = \"live\";\n setViewMode(\"live\");\n initialWindowLoadedRef.current = false;\n reconcileAfterPageResumeRef.current = false;\n }\n // AbortController is advisory: custom SDK clients and async iterators may\n // ignore it and resolve/yield after cleanup. Fence every effect instance so\n // only the newest dependency generation can mutate refs or React state.\n const generation = generationRef.current + 1;\n generationRef.current = generation;\n if (!sessionId || !streamEnabled) {\n // A page that stayed hidden beyond the live-activity grace deliberately\n // closed its SSE connection. Replaying from the old cursor on return can\n // drip a large background backlog through React in many fast batches and\n // leave the pinned camera catching up long after the user is foregrounded.\n // Remember that suspension so the next live effect replaces the browser\n // window with one compact durable tail instead.\n if (\n sessionId &&\n enabled &&\n !pageLive &&\n !fullReplay &&\n viewModeRef.current === \"live\" &&\n initialWindowLoadedRef.current\n ) {\n reconcileAfterPageResumeRef.current = true;\n }\n setConnectionState(\"idle\");\n return;\n }\n // History view owns a non-tip window; do not open SSE (it would replay the\n // entire gap into the browser). jumpToLatest / catching loadNewer resume live.\n if (viewMode === \"history\") {\n reconcileAfterPageResumeRef.current = false;\n setConnectionState(\"idle\");\n setInitialLoading(false);\n return;\n }\n const reconcileForegroundResume = reconcileAfterPageResumeRef.current && !fullReplay;\n reconcileAfterPageResumeRef.current = false;\n const controller = new AbortController();\n const isCurrent = () =>\n generationRef.current === generation &&\n !controller.signal.aborted &&\n navigationIdentityRef.current.client === client &&\n navigationIdentityRef.current.streamKey === streamKey &&\n navigationIdentityRef.current.enabled === enabled;\n streamAbortRef.current = controller;\n // Batch yielded events into one React update per flush window so a long\n // replay (thousands of events) does not render per event. Project every\n // event before retaining it here and synchronously flush at independent\n // count+byte high-water marks: a synchronously yielding async iterator can\n // otherwise starve the 16 ms timer and grow this pre-React buffer without\n // bound even though the final browser window is bounded.\n let pending: SessionEvent[] = [];\n let pendingBytes = 2; // []\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n const flush = () => {\n // A synchronous count/byte high-water flush can run before the scheduled\n // callback gets a macrotask. Cancel that callback before clearing its\n // handle so a long synchronously yielding replay retains at most one\n // timer rather than one stale callback per flushed batch.\n if (flushTimer !== null) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n if (!isCurrent()) {\n pending = [];\n pendingBytes = 2;\n return;\n }\n if (pending.length === 0) {\n return;\n }\n const batch = pending;\n pending = [];\n pendingBytes = 2;\n // The resume cursor only advances with delivered batches: events still\n // sitting in `pending` when the stream is torn down are re-fetched on\n // the next connect instead of being skipped.\n const lastInBatch = batch[batch.length - 1];\n if (lastInBatch) {\n const batchResumeSequence = Math.max(...batch.map(eventResumeSequence));\n lastSequenceRef.current = Math.max(lastSequenceRef.current, batchResumeSequence);\n streamResumeSequenceRef.current = Math.max(\n streamResumeSequenceRef.current,\n batchResumeSequence,\n );\n }\n const status = observeSessionStatus(batch, sessionStatusRef);\n if (status !== undefined) {\n setSessionStatusProjection(status);\n }\n const current = eventWindowRef.current;\n const next = appendBrowserSessionEventWindow(current, batch);\n const retained = {\n ...next,\n truncated: current.truncated || next.truncated,\n };\n eventWindowRef.current = retained;\n setEventWindow(retained);\n oldestSequenceRef.current = retained.events[0]?.sequence ?? null;\n newestSequenceRef.current = maxResumeSequenceOrNull(retained.events);\n if (retained.truncated) {\n hasOlderRef.current = true;\n setHasOlder(true);\n }\n };\n const scheduleFlush = () => {\n if (!isCurrent()) return;\n flushTimer ??= setTimeout(flush, 16);\n };\n\n void (async () => {\n try {\n if (reconcileForegroundResume) {\n setConnectionState(\"connecting\");\n const cursor = streamResumeSequenceRef.current;\n let plan: ForegroundCatchupPlan = { kind: \"resume\" };\n try {\n plan = await planForegroundCatchup(client, workspaceId, sessionId, cursor, {\n signal: controller.signal,\n });\n } catch {\n if (controller.signal.aborted) return;\n // This read is an optimization gate, not a new availability\n // dependency. If it fails, preserve the SDK's exact cursor replay\n // rather than blanking a usable timeline or failing the stream.\n plan = { kind: \"resume\" };\n }\n if (!isCurrent()) return;\n if (plan.kind === \"append\") {\n const current = eventWindowRef.current;\n assertAppendOrder(current.events, plan.events);\n const status = observeSessionStatus(plan.events, sessionStatusRef);\n const next = appendBrowserSessionEventWindow(current, plan.events);\n const retained = {\n ...next,\n truncated: current.truncated || next.truncated,\n };\n eventWindowRef.current = retained;\n oldestSequenceRef.current = retained.events[0]?.sequence ?? null;\n newestSequenceRef.current = maxResumeSequenceOrNull(retained.events);\n lastSequenceRef.current = Math.max(lastSequenceRef.current, plan.resumeSequence);\n streamResumeSequenceRef.current = Math.max(\n streamResumeSequenceRef.current,\n plan.resumeSequence,\n );\n if (status !== undefined) {\n setSessionStatusProjection(status);\n }\n setEventWindow(retained);\n if (retained.truncated) {\n hasOlderRef.current = true;\n setHasOlder(true);\n }\n } else if (plan.kind === \"reload\") {\n // A large/complex missed window would make the foreground timeline\n // and pinned camera chase many rapid commits. Keep the last known\n // complete window visible until the bounded latest replacement is\n // ready, then install that replacement atomically below.\n initialWindowLoadedRef.current = false;\n setError(null);\n }\n }\n if (!fullReplay && !initialWindowLoadedRef.current) {\n setConnectionState(\"connecting\");\n // First paint is ONE compact fetch — the newest window, revealed at\n // the bottom in a few hundred ms. Deeper history loads only when the\n // reader actually scrolls up (the sentinel drives loadOlder).\n const window = await loadEventWindow(client, workspaceId, sessionId, {\n before: Number.MAX_SAFE_INTEGER,\n pageSize: SESSION_HISTORY_PAGE_SIZE,\n targetGroups: Number.POSITIVE_INFINITY,\n maxFetches: INITIAL_FETCH_CAP,\n boundaryPageCap: BOUNDARY_PAGE_CAP,\n signal: controller.signal,\n });\n if (!isCurrent()) {\n return;\n }\n const status = observeSessionStatus(window.events, sessionStatusRef);\n const retained = boundBrowserSessionEventWindow(window.events);\n // A replacement tail retires requests against the discarded window.\n // Ordinary SSE reconnects preserve navigation, but splicing an old\n // page into this new tail could leave an inaccessible history gap.\n navigationGenerationRef.current += 1;\n loadingOlderRef.current = false;\n loadingNewerRef.current = false;\n loadingOldestRef.current = false;\n setLoadingOlder(false);\n setLoadingNewer(false);\n setLoadingOldest(false);\n eventWindowRef.current = retained;\n oldestSequenceRef.current = retained.events[0]?.sequence ?? window.oldestSequence;\n newestSequenceRef.current =\n maxResumeSequenceOrNull(retained.events) ?? window.newestSequence;\n hasOlderRef.current = window.hasOlder || retained.truncated;\n hasNewerRef.current = false;\n lastSequenceRef.current = window.newestSequence;\n streamResumeSequenceRef.current = window.newestSequence;\n initialWindowLoadedRef.current = true;\n setInitialHistoryReady(true);\n setError(null);\n if (status !== undefined) {\n setSessionStatusProjection(status);\n }\n setEventWindow(retained);\n setHasOlder(window.hasOlder || retained.truncated);\n setHasNewer(false);\n setInitialLoading(false);\n }\n if (fullReplay) {\n setInitialLoading(false);\n }\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: streamResumeSequenceRef.current,\n signal: controller.signal,\n onOpen: () => {\n // Reconciliation repairs projections, but it must not block reading\n // the already-open SSE body. Otherwise live events accumulate in the\n // browser and appear as one delayed burst after every reconciler ends.\n void Promise.resolve()\n .then(() => reconcileSession(sessionId))\n .catch((cause) => {\n if (isCurrent()) {\n setError(normalizeError(cause));\n }\n });\n },\n onStateChange: (state) => {\n if (isCurrent()) {\n setConnectionState(state);\n }\n },\n });\n for await (const event of stream) {\n if (!isCurrent()) break;\n const boundedEvent = event;\n const boundedEventBytes = browserJsonBytes(boundedEvent);\n const separatorBytes = pending.length === 0 ? 0 : 1;\n if (\n pending.length > 0 &&\n (pending.length >= SESSION_EVENT_BROWSER_PENDING_MAX_COUNT ||\n pendingBytes + separatorBytes + boundedEventBytes >\n SESSION_EVENT_BROWSER_PENDING_MAX_BYTES)\n ) {\n flush();\n }\n pending.push(boundedEvent);\n pendingBytes += (pending.length === 1 ? 0 : 1) + boundedEventBytes;\n if (\n pending.length >= SESSION_EVENT_BROWSER_PENDING_MAX_COUNT ||\n pendingBytes >= SESSION_EVENT_BROWSER_PENDING_MAX_BYTES\n ) {\n flush();\n } else {\n scheduleFlush();\n }\n }\n if (isCurrent()) {\n flush();\n setConnectionState(\"ended\");\n }\n } catch (cause) {\n if (isCurrent()) {\n flush();\n setError(normalizeError(cause));\n setConnectionState(\"error\");\n // A failed first compact-tail request has no later success path in\n // this effect instance. End the loading gate so hosts can render the\n // retryable error instead of an infinite initial spinner.\n setInitialLoading(false);\n }\n }\n })();\n\n return () => {\n controller.abort();\n if (generationRef.current === generation) {\n generationRef.current = generation + 1;\n }\n if (streamAbortRef.current === controller) {\n streamAbortRef.current = null;\n }\n if (flushTimer !== null) {\n clearTimeout(flushTimer);\n }\n };\n }, [\n client,\n workspaceId,\n sessionId,\n after,\n enabled,\n pageLive,\n streamEnabled,\n fullReplay,\n streamKey,\n streamEpoch,\n viewMode,\n reconcileSession,\n ]);\n\n const navigationBusy = (): boolean =>\n loadingTargetRef.current ||\n loadingOlderRef.current ||\n loadingNewerRef.current ||\n loadingOldestRef.current ||\n loadingLatestRef.current;\n\n const loadOlder = useCallback(\n (): OlderHistoryLoadReceipt =>\n createOlderHistoryLoadReceipt(async (markCommitted, preserveTail, markTailPreserved) => {\n if (!ownsNavigation() || !sessionId || navigationBusy() || !hasOlderRef.current) {\n return false;\n }\n const before = oldestSequenceRef.current;\n if (before === null) {\n oldestSequenceRef.current = null;\n hasOlderRef.current = false;\n setHasOlder(false);\n return false;\n }\n const generation = navigationGenerationRef.current;\n const isCurrent = () => ownsNavigation() && navigationGenerationRef.current === generation;\n loadingOlderRef.current = true;\n setLoadingOlder(true);\n let published = false;\n try {\n const window = await loadEventWindow(client, workspaceId, sessionId, {\n before,\n pageSize: SESSION_HISTORY_PAGE_SIZE,\n targetGroups: OLDER_GROUP_TARGET,\n maxFetches: OLDER_FETCH_CAP,\n isCurrent,\n });\n if (!isCurrent()) {\n return false;\n }\n if (window.events.length === 0) {\n oldestSequenceRef.current = null;\n hasOlderRef.current = false;\n setHasOlder(false);\n return false;\n }\n const current = eventWindowRef.current;\n assertPrependOrder(current.events, window.events);\n // Freeze the live iterator before replacing its in-memory window. Rows\n // pending in the aborted iterator were never cursor-committed and will\n // be replayed from the retained high-water mark below.\n const next = boundBrowserSessionEventWindow([...window.events, ...current.events], {\n direction: \"oldest\",\n });\n if (preserveTail && maxResumeSequence(next.events) < maxResumeSequence(current.events)) {\n // Automatic viewport filling must not navigate away from the\n // reader's retained tail. Explicit history navigation may do so.\n markTailPreserved();\n return false;\n }\n streamAbortRef.current?.abort();\n const status = observeSessionStatus(window.events, sessionStatusRef);\n const retained = {\n ...next,\n truncated: current.truncated || next.truncated,\n };\n const retainedOldest = retained.events[0]?.sequence ?? null;\n if (retainedOldest === null || retainedOldest >= before) {\n throw new Error(\"@opengeni/react: loadOlder made no durable sequence progress\");\n }\n const retainedNewest = maxResumeSequenceOrNull(retained.events);\n const previousNewest = maxResumeSequenceOrNull(current.events);\n eventWindowRef.current = retained;\n markCommitted();\n oldestSequenceRef.current = retainedOldest;\n newestSequenceRef.current = retainedNewest;\n streamResumeSequenceRef.current = maxResumeSequence(retained.events);\n // Oldest-directed eviction can discard newer in-memory rows. That fact\n // keeps windowTruncated true, but it does not imply older durable rows\n // exist; only the backward DB page can answer hasOlder truthfully.\n const olderStillAvailable = window.hasOlder;\n hasOlderRef.current = olderStillAvailable;\n const evictedLiveTail =\n previousNewest !== null && retainedNewest !== null && retainedNewest < previousNewest;\n let newer: boolean | null = null;\n let enterHistory = false;\n let reconnectLive = false;\n if (viewModeRef.current === \"history\" || evictedLiveTail) {\n const highWater = lastSequenceRef.current;\n newer = retainedNewest !== null && (retainedNewest < highWater || retained.truncated);\n hasNewerRef.current = newer;\n if (evictedLiveTail) {\n // A full oldest-directed browser window cannot also retain the\n // live suffix. Keep the newly loaded history and page forward;\n // reconnecting SSE here immediately newest-bounds the window and\n // evicts every row the reader just requested.\n viewModeRef.current = \"history\";\n enterHistory = true;\n }\n } else {\n // The retained merge is still one contiguous live suffix. Restart\n // SSE from its cursor so events queued during the fetch are replayed.\n reconnectLive = true;\n }\n loadingOlderRef.current = false;\n startTransition(() => {\n if (status !== undefined) {\n setSessionStatusProjection(status);\n }\n setEventWindow(retained);\n setHasOlder(olderStillAvailable);\n if (newer !== null) {\n setHasNewer(newer);\n }\n if (enterHistory) {\n setViewMode(\"history\");\n } else if (reconnectLive) {\n setStreamEpoch((epoch) => epoch + 1);\n }\n setLoadingOlder(false);\n });\n published = true;\n return olderStillAvailable;\n } catch (reason) {\n if (!isCurrent()) return false;\n throw reason;\n } finally {\n if (!published && isCurrent()) {\n loadingOlderRef.current = false;\n setLoadingOlder(false);\n }\n }\n }),\n [client, workspaceId, sessionId, ownsNavigation],\n );\n\n const loadOldest = useCallback(async (): Promise<boolean> => {\n if (!ownsNavigation() || !sessionId || navigationBusy() || !hasOlderRef.current) {\n return false;\n }\n // Explicit window replacement supersedes unresolved question destinations.\n const generation = ++navigationGenerationRef.current;\n const isCurrent = () => ownsNavigation() && navigationGenerationRef.current === generation;\n setQuestionEvidence(null);\n loadingOldestRef.current = true;\n setLoadingOldest(true);\n let published = false;\n try {\n const window = await loadForwardEventWindow(client, workspaceId, sessionId, {\n after: 0,\n pageSize: SESSION_HISTORY_PAGE_SIZE,\n targetGroups: OLDEST_GROUP_TARGET,\n maxFetches: OLDEST_FETCH_CAP,\n isCurrent,\n });\n if (!isCurrent()) {\n return false;\n }\n if (window.events.length === 0) {\n hasOlderRef.current = false;\n setHasOlder(false);\n return false;\n }\n streamAbortRef.current?.abort();\n const status = observeSessionStatus(window.events, sessionStatusRef);\n // Keep the oldest prefix — never the middle or tip.\n const retained = boundBrowserSessionEventWindow(window.events, { direction: \"oldest\" });\n const retainedOldest = retained.events[0]?.sequence ?? null;\n const retainedNewest = maxResumeSequenceOrNull(retained.events);\n eventWindowRef.current = retained;\n oldestSequenceRef.current = retainedOldest;\n newestSequenceRef.current = retainedNewest;\n hasOlderRef.current = false;\n const highWater = Math.max(lastSequenceRef.current, retainedNewest ?? 0);\n lastSequenceRef.current = highWater;\n const newer =\n window.hasNewer ||\n retained.truncated ||\n (retainedNewest !== null && retainedNewest < highWater);\n hasNewerRef.current = newer;\n initialWindowLoadedRef.current = true;\n setInitialHistoryReady(true);\n setError(null);\n viewModeRef.current = \"history\";\n loadingOldestRef.current = false;\n setNewerError(null);\n startTransition(() => {\n if (status !== undefined) {\n setSessionStatusProjection(status);\n }\n setEventWindow(retained);\n setHasOlder(false);\n setHasNewer(newer);\n setViewMode(\"history\");\n setLoadingOldest(false);\n });\n published = true;\n return newer;\n } catch (reason) {\n if (!isCurrent()) return false;\n throw reason;\n } finally {\n if (!published && isCurrent()) {\n loadingOldestRef.current = false;\n setLoadingOldest(false);\n }\n }\n }, [client, workspaceId, sessionId, ownsNavigation]);\n\n const loadNewer = useCallback(async (): Promise<boolean> => {\n if (!ownsNavigation() || !sessionId || navigationBusy() || !hasNewerRef.current) {\n return false;\n }\n const afterSequence = newestSequenceRef.current;\n if (afterSequence === null) {\n hasNewerRef.current = false;\n setHasNewer(false);\n return false;\n }\n const generation = navigationGenerationRef.current;\n const isCurrent = () => ownsNavigation() && navigationGenerationRef.current === generation;\n loadingNewerRef.current = true;\n setLoadingNewer(true);\n let published = false;\n try {\n const window = await loadForwardEventWindow(client, workspaceId, sessionId, {\n after: afterSequence,\n pageSize: SESSION_HISTORY_PAGE_SIZE,\n targetGroups: NEWER_GROUP_TARGET,\n maxFetches: NEWER_FETCH_CAP,\n isCurrent,\n });\n if (!isCurrent()) {\n return false;\n }\n if (window.events.length === 0) {\n setNewerError(null);\n hasNewerRef.current = false;\n setHasNewer(false);\n // Caught up with durable history — resume the live tip stream.\n streamResumeSequenceRef.current = afterSequence;\n viewModeRef.current = \"live\";\n setViewMode(\"live\");\n setStreamEpoch((epoch) => epoch + 1);\n return false;\n }\n const current = eventWindowRef.current;\n assertAppendOrder(current.events, window.events);\n const status = observeSessionStatus(window.events, sessionStatusRef);\n const previousOldest = current.events[0]?.sequence ?? null;\n // Moving forward through history: keep the newest suffix of the merge.\n const next = appendBrowserSessionEventWindow(current, window.events);\n const retained = {\n ...next,\n truncated: current.truncated || next.truncated || window.hasNewer,\n };\n const retainedOldest = retained.events[0]?.sequence ?? null;\n const retainedNewest = maxResumeSequenceOrNull(retained.events);\n if (retainedNewest === null || retainedNewest <= afterSequence) {\n throw new Error(\"@opengeni/react: loadNewer made no durable sequence progress\");\n }\n eventWindowRef.current = retained;\n oldestSequenceRef.current = retainedOldest;\n newestSequenceRef.current = retainedNewest;\n // Evicting the start while paging forward re-arms hasOlder.\n if (\n retainedOldest !== null &&\n (previousOldest === null ||\n retainedOldest > previousOldest ||\n (retained.truncated &&\n retained.events[0]?.type !== \"session.created\" &&\n retainedOldest > 1))\n ) {\n hasOlderRef.current = true;\n }\n const rearmedOlder = hasOlderRef.current;\n const highWater = Math.max(lastSequenceRef.current, retainedNewest);\n lastSequenceRef.current = highWater;\n const newer = window.hasNewer || retainedNewest < highWater;\n hasNewerRef.current = newer;\n let resumeLive = false;\n if (!newer) {\n streamResumeSequenceRef.current = retainedNewest;\n viewModeRef.current = \"live\";\n resumeLive = true;\n }\n loadingNewerRef.current = false;\n setNewerError(null);\n startTransition(() => {\n if (status !== undefined) {\n setSessionStatusProjection(status);\n }\n setEventWindow(retained);\n setHasOlder(rearmedOlder);\n setHasNewer(newer);\n if (resumeLive) {\n setViewMode(\"live\");\n setStreamEpoch((epoch) => epoch + 1);\n }\n setLoadingNewer(false);\n });\n published = true;\n return newer;\n } catch (reason) {\n // A settled request from an old navigation lifetime is not a failure of\n // the current session. Preserve current loading/error state as well.\n if (!isCurrent()) {\n return false;\n }\n setNewerError(normalizeError(reason));\n // Keep authorization and integrity failures actionable for callers;\n // timeline-owned invocations attach their own explicit recovery UI.\n throw reason;\n } finally {\n if (!published && isCurrent()) {\n loadingNewerRef.current = false;\n setLoadingNewer(false);\n }\n }\n }, [client, workspaceId, sessionId, ownsNavigation]);\n\n const jumpToSequence = useCallback(\n async (sequence: number, navigationOptions?: { signal?: AbortSignal }): Promise<boolean> => {\n const signal = navigationOptions?.signal;\n if (!ownsNavigation() || !sessionId || !Number.isSafeInteger(sequence) || sequence < 1)\n return false;\n // A navigation that was already cancelled (for example Find closed before\n // the caller could react) must not disturb any current view state.\n if (signal?.aborted) return false;\n // Explicit targets supersede both other targets and adjacent-page requests.\n const generation = ++navigationGenerationRef.current;\n setQuestionEvidence(null);\n const current = () => generation === navigationGenerationRef.current && ownsNavigation();\n const previousMode = viewModeRef.current;\n streamAbortRef.current?.abort();\n generationRef.current += 1;\n viewModeRef.current = \"history\";\n setViewMode(\"history\");\n loadingOlderRef.current = loadingNewerRef.current = loadingOldestRef.current = false;\n setLoadingOlder(false);\n setLoadingNewer(false);\n setLoadingOldest(false);\n loadingTargetRef.current = true;\n setLoadingTarget(true);\n let published = false;\n try {\n const [before, following] = await Promise.all([\n loadPreviousPage(client, workspaceId, sessionId, sequence + 1, { pageSize: 128 }),\n loadNextPage(client, workspaceId, sessionId, sequence, { pageSize: 128 }),\n ]);\n // Close-during-fetch fence: a pending jump must not replace the window\n // after its owner (for example ConversationFind) has gone away. The\n // finally block still settles loadingTarget for this generation.\n if (signal?.aborted) return false;\n if (!current()) return false;\n if (!before.some((event) => event.sequence === sequence)) return false;\n // Bound each side, keeping the target even if its message alone exceeds\n // the ordinary byte budget. Never evict the very event being navigated to.\n const prefix = boundBrowserSessionEventWindow(before, {\n direction: \"newest\",\n maxBytes: SESSION_EVENT_BROWSER_MAX_BYTES / 2,\n });\n const retained = boundBrowserSessionEventWindow([...prefix.events, ...following], {\n direction: \"oldest\",\n });\n if (!retained.events.some((event) => event.sequence === sequence)) return false;\n streamAbortRef.current?.abort();\n generationRef.current += 1;\n const status = observeSessionStatus(retained.events, sessionStatusRef);\n eventWindowRef.current = retained;\n oldestSequenceRef.current = retained.events[0]!.sequence;\n newestSequenceRef.current = maxResumeSequenceOrNull(retained.events);\n lastSequenceRef.current = Math.max(lastSequenceRef.current, newestSequenceRef.current ?? 0);\n hasOlderRef.current = !isLogStart(retained.events[0]!);\n // Compact/byte-bounded pages may be short despite more durable history.\n // Only an empty forward page proves the end (same rule as loadNewer).\n hasNewerRef.current =\n following.length > 0 ||\n retained.truncated ||\n (newestSequenceRef.current ?? 0) < lastSequenceRef.current;\n initialWindowLoadedRef.current = true;\n setInitialHistoryReady(true);\n setError(null);\n viewModeRef.current = \"history\";\n setEventWindow(retained);\n setHasOlder(hasOlderRef.current);\n setHasNewer(hasNewerRef.current);\n setInitialLoading(false);\n setViewMode(\"history\");\n setNewerError(null);\n if (status !== undefined) setSessionStatusProjection(status);\n published = true;\n return true;\n } catch (reason) {\n if (!current() || signal?.aborted) return false;\n throw reason;\n } finally {\n if (current()) {\n loadingTargetRef.current = false;\n setLoadingTarget(false);\n if (!published && previousMode === \"live\") {\n viewModeRef.current = \"live\";\n setViewMode(\"live\");\n setStreamEpoch((epoch) => epoch + 1);\n }\n }\n }\n },\n [client, workspaceId, sessionId, ownsNavigation],\n );\n\n const jumpToLatestQuestion = useCallback(\n async (questionOptions?: LatestQuestionOptions): Promise<number | null> => {\n if (!sessionId || !ownsNavigation()) return null;\n let generation = navigationGenerationRef.current;\n const current = () => ownsNavigation() && generation === navigationGenerationRef.current;\n try {\n // Optional action code stays off the session-open path. Capture identity\n // before the import and fence its completion just like network reads.\n const { resolveLatestQuestion } = await import(\"./latest-question\");\n if (!current()) return null;\n const destination = await resolveLatestQuestion({\n client,\n workspaceId,\n sessionId,\n isCurrent: current,\n resumeSequence: maxResumeSequence,\n options: questionOptions,\n });\n if (!destination || !current()) return null;\n if (!eventWindowRef.current.events.some((event) => event.sequence === destination.anchor)) {\n const navigation = jumpToSequence(destination.anchor);\n generation = navigationGenerationRef.current;\n if (!(await navigation) || !current()) return null;\n }\n setQuestionEvidence({\n client,\n streamKey,\n anchor: destination.anchor,\n events: destination.events,\n });\n return destination.questionSequence;\n } catch (reason) {\n if (!current()) return null;\n throw reason;\n }\n },\n [client, workspaceId, sessionId, streamKey, ownsNavigation, jumpToSequence],\n );\n\n const jumpToLatest = useCallback(async (): Promise<void> => {\n // An old host retry closure must not clear a replacement session's error\n // or abort its live feed before the passive effect cleanup has run.\n if (!ownsNavigation()) return;\n if (loadingTargetRef.current) {\n navigationGenerationRef.current += 1;\n loadingTargetRef.current = false;\n setLoadingTarget(false);\n }\n if (!sessionId || navigationBusy()) {\n return;\n }\n navigationGenerationRef.current += 1;\n setQuestionEvidence(null);\n loadingLatestRef.current = true;\n setLoadingLatest(true);\n setNewerError(null);\n setError(null);\n let published = false;\n try {\n streamAbortRef.current?.abort();\n hasNewerRef.current = false;\n hasOlderRef.current = false;\n newestSequenceRef.current = null;\n oldestSequenceRef.current = null;\n eventWindowRef.current = EMPTY_EVENT_WINDOW;\n initialWindowLoadedRef.current = false;\n streamResumeSequenceRef.current = after;\n viewModeRef.current = \"live\";\n loadingLatestRef.current = false;\n startTransition(() => {\n setHasNewer(false);\n setHasOlder(false);\n setEventWindow(EMPTY_EVENT_WINDOW);\n setInitialLoading(true);\n setViewMode(\"live\");\n setStreamEpoch((epoch) => epoch + 1);\n setLoadingLatest(false);\n });\n published = true;\n // Effect reloads the tip. The tip fetch itself is owned by the effect.\n await Promise.resolve();\n } finally {\n if (!published) {\n loadingLatestRef.current = false;\n setLoadingLatest(false);\n }\n }\n }, [after, sessionId, ownsNavigation]);\n\n const identityMatches = stateStreamKey === streamKey;\n const visibleEvents = identityMatches ? eventWindow.events : EMPTY_EVENTS;\n const timeline = useMemo(() => {\n const witness =\n questionEvidence?.client === client &&\n questionEvidence.streamKey === streamKey &&\n visibleEvents.some((event) => event.sequence === questionEvidence.anchor)\n ? questionEvidence.events\n : EMPTY_EVENTS;\n const timelineOptions = { partialStart: hasOlder || eventWindow.truncated || after > 0 };\n if (witness.length === 0) return buildTimeline(visibleEvents, timelineOptions);\n const ids = new Set(visibleEvents.map((event) => event.id));\n return buildTimeline(\n [...visibleEvents, ...witness.filter((event) => !ids.has(event.id))],\n timelineOptions,\n );\n }, [visibleEvents, hasOlder, eventWindow.truncated, after, questionEvidence, client, streamKey]);\n\n return {\n events: visibleEvents,\n timeline,\n sessionStatus: identityMatches ? sessionStatusProjection : null,\n sessionStatusSequence: identityMatches ? sessionStatusRef.current.sequence : 0,\n connectionState: identityMatches ? connectionState : \"idle\",\n lastSequence: identityMatches ? lastSequenceRef.current : after,\n windowBytes: identityMatches ? eventWindow.bytes : 2,\n windowTruncated: identityMatches ? eventWindow.truncated : false,\n initialLoading: fullReplay ? false : identityMatches ? initialLoading : true,\n initialHistoryReady: identityMatches && initialHistoryReady,\n hasOlder: !identityMatches ? false : hasOlder,\n loadingOlder: !identityMatches ? false : loadingOlder,\n loadOlder,\n hasNewer: !identityMatches ? false : hasNewer,\n loadingNewer: !identityMatches ? false : loadingNewer,\n loadNewer,\n loadingOldest: !identityMatches ? false : loadingOldest,\n loadOldest,\n loadingLatest: !identityMatches ? false : loadingLatest,\n jumpToLatest,\n jumpToLatestQuestion,\n jumpToSequence,\n loadingTarget: identityMatches && loadingTarget,\n error: identityMatches ? (newerError ?? error) : null,\n };\n}\n\n/**\n * Keep one direction-aware count+byte-bounded browser window. Live/default\n * accumulation retains the newest suffix; backward paging retains the oldest\n * prefix so newly fetched history cannot be immediately evicted. This is\n * deliberately separate from durable history and transport paging: when a\n * backward page evicts the live tail, the hook enters bounded history mode and\n * preserves the highest-ever-observed sequence separately for forward paging.\n * The source event remains durable in PostgreSQL throughout. An event larger\n * than the byte target is retained alone, never replaced by a lossy preview.\n */\nexport function boundBrowserSessionEventWindow(\n events: readonly SessionEvent[],\n options: {\n maxBytes?: number;\n maxCount?: number;\n direction?: \"newest\" | \"oldest\";\n } = {},\n): BrowserSessionEventWindow {\n const maxBytes = Math.max(1024, options.maxBytes ?? SESSION_EVENT_BROWSER_MAX_BYTES);\n const maxCount = Math.max(1, Math.floor(options.maxCount ?? SESSION_EVENT_BROWSER_MAX_COUNT));\n const safe = events;\n const selected: SessionEvent[] = [];\n let bytes = 2; // []\n const direction = options.direction ?? \"newest\";\n const start = direction === \"newest\" ? safe.length - 1 : 0;\n const end = direction === \"newest\" ? Math.max(-1, safe.length - maxCount - 1) : safe.length;\n const step = direction === \"newest\" ? -1 : 1;\n for (let index = start; index !== end && selected.length < maxCount; index += step) {\n const event = safe[index]!;\n const eventBytes = browserJsonBytes(event);\n const separator = selected.length === 0 ? 0 : 1;\n if (selected.length > 0 && bytes + separator + eventBytes > maxBytes) break;\n selected.push(event);\n bytes += separator + eventBytes;\n }\n if (direction === \"newest\") selected.reverse();\n return {\n events: selected,\n bytes,\n truncated: selected.length < safe.length,\n };\n}\n\n/** @internal Append immutable events without serializing the retained history again. */\nexport function appendBrowserSessionEventWindow(\n current: BrowserSessionEventWindow,\n batch: readonly SessionEvent[],\n options: { maxBytes?: number; maxCount?: number } = {},\n): BrowserSessionEventWindow {\n const maxBytes = Math.max(1024, options.maxBytes ?? SESSION_EVENT_BROWSER_MAX_BYTES);\n const maxCount = Math.max(1, Math.floor(options.maxCount ?? SESSION_EVENT_BROWSER_MAX_COUNT));\n const events = [...current.events, ...batch];\n let bytes = current.bytes;\n for (let index = 0; index < batch.length; index += 1) {\n bytes += browserJsonBytes(batch[index]) + (current.events.length + index > 0 ? 1 : 0);\n }\n let start = 0;\n // Preserve the newest event even when it alone exceeds the byte target,\n // matching the full-window reducer and retaining exact cursor progress.\n while (events.length - start > 1 && (bytes > maxBytes || events.length - start > maxCount)) {\n bytes -= browserJsonBytes(events[start]) + 1;\n start += 1;\n }\n return {\n events: start === 0 ? events : events.slice(start),\n bytes,\n truncated: current.truncated || start > 0,\n };\n}\n\nfunction browserJsonBytes(value: unknown): number {\n return encoder.encode(JSON.stringify(value)).byteLength;\n}\n\nfunction observeSessionStatus(\n events: readonly SessionEvent[],\n ref: { current: { sequence: number; status: SessionStatus | null } },\n): SessionStatus | undefined {\n let latest: { sequence: number; status: SessionStatus } | null = null;\n for (const event of events) {\n const status = sessionStatusFromEvents([event]);\n if (status && (!latest || event.sequence >= latest.sequence)) {\n latest = { sequence: event.sequence, status };\n }\n }\n if (!latest || latest.sequence < ref.current.sequence) return undefined;\n ref.current = latest;\n return latest.status;\n}\n\ntype ForegroundCatchupPlan =\n | { kind: \"resume\" }\n | { kind: \"append\"; events: SessionEvent[]; resumeSequence: number }\n | { kind: \"reload\" };\n\n/**\n * Decide how a sustained hidden-tab suspension rejoins the durable event log.\n *\n * `lastSequence - cursor` is the exact raw durable work missed, but it is not\n * the number of visible messages: one streaming answer can own thousands of\n * adjacent delta rows. Small raw gaps therefore resume directly; medium gaps\n * get one forward compact page and are judged by the browser-visible result;\n * a page that cannot prove complete bounded coverage, or that would add too\n * many rows/groups/bytes, reloads the latest tail instead.\n */\nasync function planForegroundCatchup(\n client: EmbeddedSessionClientLike,\n workspaceId: string,\n sessionId: string,\n cursor: number,\n options: { signal?: AbortSignal } = {},\n): Promise<ForegroundCatchupPlan> {\n if (options.signal?.aborted) throw abortError();\n const session = await client.getSession(workspaceId, sessionId, {\n fresh: true,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n if (options.signal?.aborted) throw abortError();\n const durableHead = Math.max(cursor, session.lastSequence);\n const rawGap = durableHead - cursor;\n if (rawGap <= FOREGROUND_DIRECT_REPLAY_MAX_SEQUENCES) {\n return { kind: \"resume\" };\n }\n if (rawGap > FOREGROUND_COMPACT_PROBE_MAX_SEQUENCES) {\n return { kind: \"reload\" };\n }\n\n const page = await loadNextPage(client, workspaceId, sessionId, cursor, {\n pageSize: rawGap,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n const events = page.filter((event) => eventResumeSequence(event) > cursor);\n if (events.length === 0) {\n return { kind: \"reload\" };\n }\n assertAscending(events);\n const resumeSequence = maxResumeSequence(events);\n if (resumeSequence < durableHead) {\n // Byte/count truncation or an incomplete projection means this page cannot\n // prove that one append reaches the head observed above.\n return { kind: \"reload\" };\n }\n if (\n events.length > FOREGROUND_COMPACT_CATCHUP_MAX_EVENTS ||\n groupCount(events) > FOREGROUND_COMPACT_CATCHUP_MAX_GROUPS ||\n browserJsonBytes(events) > FOREGROUND_COMPACT_CATCHUP_MAX_BYTES\n ) {\n return { kind: \"reload\" };\n }\n return { kind: \"append\", events, resumeSequence };\n}\n\ntype LoadedEventWindow = {\n events: SessionEvent[];\n oldestSequence: number | null;\n newestSequence: number;\n hasOlder: boolean;\n};\n\ntype LoadedForwardEventWindow = {\n events: SessionEvent[];\n oldestSequence: number | null;\n newestSequence: number;\n hasNewer: boolean;\n};\n\nasync function loadEventWindow(\n client: EmbeddedSessionClientLike,\n workspaceId: string,\n sessionId: string,\n options: {\n before: number;\n pageSize: number;\n targetGroups: number;\n maxFetches: number;\n boundaryPageCap?: number;\n signal?: AbortSignal;\n isCurrent?: () => boolean;\n },\n): Promise<LoadedEventWindow> {\n let cursor = options.before;\n let buffer: SessionEvent[] = [];\n let reachedStart = false;\n let fetches = 0;\n\n while (fetches < options.maxFetches) {\n if (buffer.length > 0 && groupCount(buffer) >= options.targetGroups) {\n break;\n }\n const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {\n pageSize: options.pageSize,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n if (options.isCurrent?.() === false) throw abortError();\n fetches += 1;\n if (page.length === 0) {\n reachedStart = true;\n break;\n }\n assertAscending(page);\n buffer = [...page, ...buffer];\n cursor = page[0]!.sequence;\n if (isLogStart(page[0]!)) {\n reachedStart = true;\n break;\n }\n }\n\n // Boundary snap: a window that starts mid-turn TRIMS its head to the oldest\n // turn boundary already in the buffer — the dropped fragment is refetched by\n // the next loadOlder (everything below the new oldest sequence), whose own\n // window snaps the same way, so every seam lands on a turn start. Extra\n // page is fetched only when the buffer holds no boundary at all (one dense\n // turn); past the cap the existing truncation/hasOlder signal remains true.\n let snapPages = 0;\n while (\n !reachedStart &&\n findBoundaryIndex(buffer) === -1 &&\n snapPages < (options.boundaryPageCap ?? 0)\n ) {\n const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {\n pageSize: options.pageSize,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n if (options.isCurrent?.() === false) throw abortError();\n fetches += 1;\n snapPages += 1;\n if (page.length === 0) {\n reachedStart = true;\n break;\n }\n assertAscending(page);\n buffer = [...page, ...buffer];\n cursor = page[0]!.sequence;\n if (isLogStart(page[0]!)) {\n reachedStart = true;\n break;\n }\n }\n if (!reachedStart) {\n const boundary = findBoundaryIndex(buffer);\n if (boundary > 0) {\n buffer = buffer.slice(boundary);\n }\n }\n const densityWindow = trimBackwardToGroupTarget(buffer, options.targetGroups);\n buffer = densityWindow.events;\n\n const oldest = buffer[0] ?? null;\n const newest = buffer[buffer.length - 1] ?? null;\n return {\n events: buffer,\n oldestSequence: oldest?.sequence ?? null,\n newestSequence: newest ? maxResumeSequence(buffer) : 0,\n hasOlder:\n buffer.length > 0 &&\n (densityWindow.trimmed || (!reachedStart && oldest?.type !== \"session.created\")),\n };\n}\n\n/** Index of the oldest clean turn start in the buffer, or -1. */\nfunction findBoundaryIndex(events: SessionEvent[]): number {\n for (let index = 0; index < events.length; index += 1) {\n if (isTurnBoundary(events[index]!)) {\n return index;\n }\n }\n return -1;\n}\n\nfunction isTurnBoundary(event: SessionEvent): boolean {\n return event.type === \"session.created\" || event.type === \"user.message\";\n}\n\n/**\n * Forward (oldest→newer) density-bounded window. Used for jump-to-start and\n * loadNewer so the browser never walks the whole middle gap.\n */\nasync function loadForwardEventWindow(\n client: EmbeddedSessionClientLike,\n workspaceId: string,\n sessionId: string,\n options: {\n after: number;\n pageSize: number;\n targetGroups: number;\n maxFetches: number;\n signal?: AbortSignal;\n isCurrent?: () => boolean;\n },\n): Promise<LoadedForwardEventWindow> {\n let cursor = options.after;\n let buffer: SessionEvent[] = [];\n let fetches = 0;\n let reachedEnd = false;\n\n while (fetches < options.maxFetches) {\n if (buffer.length > 0 && groupCount(buffer) >= options.targetGroups) {\n break;\n }\n const page = await loadNextPage(client, workspaceId, sessionId, cursor, {\n pageSize: options.pageSize,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n if (options.isCurrent?.() === false) throw abortError();\n fetches += 1;\n if (page.length === 0) {\n reachedEnd = true;\n break;\n }\n assertAscending(page);\n buffer = [...buffer, ...page];\n // Compact events retain their first raw sequence in `sequence` and expose\n // the covered high-water mark through `coalescedUntil`. Advancing by the\n // first sequence duplicates compacted text on the next page. A compact\n // response length is not an end-of-history signal either: thousands of raw\n // events may legitimately collapse into one returned event.\n cursor = maxResumeSequence(page);\n }\n const densityWindow = trimForwardToGroupTarget(buffer, options.targetGroups);\n buffer = densityWindow.events;\n\n const oldest = buffer[0] ?? null;\n const newest = buffer[buffer.length - 1] ?? null;\n return {\n events: buffer,\n oldestSequence: oldest?.sequence ?? null,\n newestSequence: newest ? maxResumeSequence(buffer) : 0,\n hasNewer: buffer.length > 0 && (densityWindow.trimmed || !reachedEnd),\n };\n}\n\ntype DensityWindow = {\n events: SessionEvent[];\n trimmed: boolean;\n};\n\n/** Keep the newest complete turn groups near an older-history seam. */\nfunction trimBackwardToGroupTarget(events: SessionEvent[], targetGroups: number): DensityWindow {\n if (!Number.isFinite(targetGroups) || targetGroups <= 0 || events.length === 0) {\n return { events, trimmed: false };\n }\n for (let index = events.length - 1; index > 0; index -= 1) {\n if (!isTurnBoundary(events[index]!)) continue;\n const candidate = events.slice(index);\n if (groupCount(candidate) >= targetGroups) {\n return { events: candidate, trimmed: true };\n }\n }\n return { events, trimmed: false };\n}\n\n/** Keep the oldest complete turn groups near a forward-history seam. */\nfunction trimForwardToGroupTarget(events: SessionEvent[], targetGroups: number): DensityWindow {\n if (!Number.isFinite(targetGroups) || targetGroups <= 0 || events.length === 0) {\n return { events, trimmed: false };\n }\n for (let index = 1; index < events.length; index += 1) {\n if (!isTurnBoundary(events[index]!)) continue;\n const candidate = events.slice(0, index);\n if (groupCount(candidate) >= targetGroups) {\n return { events: candidate, trimmed: true };\n }\n }\n return { events, trimmed: false };\n}\n\ntype PreviousPage = SessionEvent[] & { requested: number };\n\nasync function loadPreviousPage(\n client: EmbeddedSessionClientLike,\n workspaceId: string,\n sessionId: string,\n before: number,\n options: {\n pageSize: number;\n signal?: AbortSignal;\n },\n): Promise<PreviousPage> {\n if (options.signal?.aborted) {\n throw abortError();\n }\n const requested = options.pageSize;\n if (requested === 0) {\n return Object.assign([], { requested });\n }\n const page = await client.listEvents(workspaceId, sessionId, {\n before,\n limit: requested,\n compact: true,\n // Monitoring summaries omit correlation fields once a bounded durable\n // payload exceeds their preview threshold. The browser timeline needs the\n // exact stored payload so persisted tool outputs still match their\n // calls and expose truthful truncation telemetry after a reload.\n payloadMode: \"full\",\n });\n if (options.signal?.aborted) {\n throw abortError();\n }\n return Object.assign(page, { requested });\n}\n\nasync function loadNextPage(\n client: EmbeddedSessionClientLike,\n workspaceId: string,\n sessionId: string,\n after: number,\n options: {\n pageSize: number;\n signal?: AbortSignal;\n },\n): Promise<PreviousPage> {\n if (options.signal?.aborted) {\n throw abortError();\n }\n const requested = options.pageSize;\n if (requested === 0) {\n return Object.assign([], { requested });\n }\n const page = await client.listEvents(workspaceId, sessionId, {\n after,\n limit: requested,\n compact: true,\n direction: \"after\",\n payloadMode: \"full\",\n });\n if (options.signal?.aborted) {\n throw abortError();\n }\n return Object.assign(page, { requested });\n}\n\nfunction groupCount(events: SessionEvent[]): number {\n if (events.length === 0) {\n return 0;\n }\n return groupTimeline(buildTimeline(events)).length;\n}\n\nfunction isLogStart(event: SessionEvent): boolean {\n return event.type === \"session.created\" || event.sequence <= 1;\n}\n\nfunction maxResumeSequence(events: readonly SessionEvent[]): number {\n return events.reduce((max, event) => Math.max(max, eventResumeSequence(event)), 0);\n}\n\nfunction maxResumeSequenceOrNull(events: readonly SessionEvent[]): number | null {\n return events.length > 0 ? maxResumeSequence(events) : null;\n}\n\nfunction eventResumeSequence(event: SessionEvent): number {\n const streamedCoverage = sessionEventStreamCoveredThrough(event);\n if (streamedCoverage !== null) return streamedCoverage;\n return typeof event.coveredThrough === \"number\" &&\n Number.isSafeInteger(event.coveredThrough) &&\n event.coveredThrough >= event.sequence\n ? event.coveredThrough\n : event.sequence;\n}\n\nfunction assertAscending(events: SessionEvent[]): void {\n for (let index = 1; index < events.length; index += 1) {\n if (events[index - 1]!.sequence >= events[index]!.sequence) {\n throw new Error(\"@opengeni/react: session events must be ordered by ascending sequence\");\n }\n }\n}\n\nfunction assertPrependOrder(existing: SessionEvent[], older: SessionEvent[]): void {\n if (!shouldAssertDevelopment() || existing.length === 0 || older.length === 0) {\n return;\n }\n if (older[older.length - 1]!.sequence >= existing[0]!.sequence) {\n throw new Error(\"@opengeni/react: loadOlder returned overlapping session events\");\n }\n}\n\nfunction assertAppendOrder(existing: SessionEvent[], newer: SessionEvent[]): void {\n if (!shouldAssertDevelopment() || existing.length === 0 || newer.length === 0) {\n return;\n }\n if (newer[0]!.sequence <= existing[existing.length - 1]!.sequence) {\n throw new Error(\"@opengeni/react: loadNewer returned overlapping session events\");\n }\n}\n\nfunction shouldAssertDevelopment(): boolean {\n const processEnv = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env;\n return processEnv !== undefined && processEnv.NODE_ENV !== \"production\";\n}\n\nfunction abortError(): Error {\n const error = new Error(\"The operation was aborted.\");\n error.name = \"AbortError\";\n return error;\n}\n","import type { Session, SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useEmbeddedSessionRead, type EmbeddedSessionReadClientOverride } from \"../session-context\";\nimport {\n useMutationRunner,\n usePolledValue,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\nexport type UseSessionOptions = EmbeddedSessionReadClientOverride &\n SessionEventFeedOptions & {\n /** Re-fetch on an interval (ms). Off by default — pair with `useSessionEvents` for live status. */\n pollIntervalMs?: number | undefined;\n /** Optional shared causal clock invoked when each network read starts. */\n beginRead?: (() => number) | undefined;\n };\n\nexport type UseSessionResult = {\n session: Session | null;\n loading: boolean;\n error: Error | null;\n /** Monotonic revision of accepted authoritative detail reads. */\n readRevision: number;\n /** Causal generation captured when the accepted network read started. */\n readGeneration: number;\n refresh: () => Promise<void>;\n /** Manually rename the session (PATCH, source='user'). Returns the updated session, or null on failure. */\n updateTitle: (title: string) => Promise<Session | null>;\n /** True while a rename is in flight. */\n updating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/** Event types that change the session title (auto + cross-client renames). */\nexport function isTitleEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return event.type === \"session.title_set\";\n}\n\nfunction isSessionDetailEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return (\n isTitleEvent(event) ||\n event.type.startsWith(\"session.command.\") ||\n event.type.startsWith(\"session.wait.\") ||\n event.type === \"session.status.changed\" ||\n event.type === \"system.update.pending\"\n );\n}\n\n/** Fetch one session (with optional polling), live-patching its title on `session.title_set`. */\nexport function useSession(\n sessionId: string | null | undefined,\n options: UseSessionOptions = {},\n): UseSessionResult {\n const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } =\n useEmbeddedSessionRead(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const [override, setOverride] = useState<Session | null>(null);\n const nextReadRevision = useRef(0);\n const nextReadGeneration = useRef(0);\n const beginRead = options.beginRead;\n const { run, mutating, mutationError, clearMutationError } = useMutationRunner();\n const load = useCallback(\n async (signal?: AbortSignal) => {\n if (!sessionId) {\n return null;\n }\n let readGeneration = 0;\n const fetched = await client.getSession(workspaceId, sessionId, {\n fresh: true,\n signal,\n onRequestStart: () => {\n readGeneration = beginRead?.() ?? ++nextReadGeneration.current;\n },\n });\n // A fresh server read supersedes any optimistic/event-driven override.\n setOverride(null);\n return {\n session: fetched,\n revision: ++nextReadRevision.current,\n readGeneration,\n };\n },\n [beginRead, client, workspaceId, sessionId],\n );\n const { data, loading, error, refresh } = usePolledValue(load, {\n pollIntervalMs: options.pollIntervalMs,\n enabled,\n });\n useEffect(() => {\n if (enabled && workspaceControlEvent) void refresh();\n }, [enabled, refresh, workspaceControlEvent]);\n useEffect(() => {\n if (!sessionId || !enabled) return;\n return registerSessionReconciler(sessionId, \"session\", refresh);\n }, [enabled, refresh, registerSessionReconciler, sessionId]);\n\n const base = data?.session ?? null;\n const readRevision = data?.revision ?? 0;\n const readGeneration = data?.readGeneration ?? 0;\n // The override only ever carries title/titleSource patches; it is reset on\n // every fresh load so it can never go stale against the server snapshot.\n const session = useMemo(\n () =>\n base && override && override.id === base.id\n ? { ...base, title: override.title, titleSource: override.titleSource }\n : base,\n [base, override],\n );\n\n const sharedEvents = options.events;\n\n // Live-patch the title on auto (agent) + cross-client (user/agent) renames so\n // the UI reflects the new title without polling or a full re-fetch.\n const onTitleEvent = useCallback(\n (event: SessionEvent) => {\n // Reconciliation emits only the last matching member of a shared batch.\n // A later title must not hide an earlier command activity change.\n if (\n sharedEvents?.some(\n (item) =>\n item.sessionId === sessionId &&\n !isTitleEvent(item) &&\n isSessionDetailEvent(item) &&\n item.sequence > (base?.lastSequence ?? -1),\n )\n ) {\n void refresh();\n } else if (!isTitleEvent(event)) {\n if (!base || event.sequence > base.lastSequence) void refresh();\n return;\n }\n // The fetched session row is the authoritative title projection through\n // lastSequence. Shared feeds may replay that historical tail after the\n // fetch; applying it would undo a row-only migration quarantine. Only an\n // event committed after this snapshot may live-patch the title.\n if (!base || event.sequence <= base.lastSequence) {\n return;\n }\n const payload = (event.payload ?? {}) as { title?: unknown; source?: unknown };\n const title = payload.title;\n if (typeof title !== \"string\") {\n return;\n }\n const source: \"user\" | \"agent\" | null =\n payload.source === \"user\" || payload.source === \"agent\" ? payload.source : null;\n setOverride((current): Session | null => {\n const next = current ?? base;\n return { ...next, title, titleSource: source };\n });\n },\n [base, refresh, sharedEvents, sessionId],\n );\n useSessionEventTrigger(client, workspaceId, sessionId, isSessionDetailEvent, onTitleEvent, {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n });\n\n const updateTitle = useCallback(\n async (title: string): Promise<Session | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await run(() => client.updateSession(workspaceId, sessionId, { title }));\n if (result) {\n setOverride(result);\n }\n return result;\n },\n [client, workspaceId, sessionId, run],\n );\n\n return {\n session,\n loading,\n error,\n readRevision,\n readGeneration,\n refresh,\n updateTitle,\n updating: mutating,\n mutationError,\n clearMutationError,\n };\n}\n","import type {\n ComposerDraft,\n EffectiveSessionControl,\n McpPersonalConnectionSummary,\n SessionEvent,\n SessionQueueMutationResponse,\n SessionQueueSnapshot,\n SessionPendingInputPreview,\n SessionTurn,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useEmbeddedSession, type EmbeddedSessionClientOverride } from \"../session-context\";\nimport { normalizeError } from \"../lib/error-message\";\nimport {\n useDebouncedCallback,\n usePageLiveActivity,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\n/** Events that can change the authoritative prompt queue or effective control. */\nexport function isTurnQueueEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return (\n event.type.startsWith(\"turn.\") ||\n event.type.startsWith(\"session.queue.\") ||\n event.type.startsWith(\"session.control.\") ||\n event.type.startsWith(\"system.update.\") ||\n event.type.startsWith(\"workspace.inference.\")\n );\n}\n\nfunction queueSnapshotCovers(\n candidate: SessionQueueSnapshot | null,\n observed: SessionQueueSnapshot,\n): boolean {\n return Boolean(\n candidate &&\n candidate.version >= observed.version &&\n candidate.effectiveControl.controlVersion >= observed.effectiveControl.controlVersion,\n );\n}\n\nexport type QueueMutationKind = \"move\" | \"edit\" | \"steer\" | \"delete\";\nconst EMPTY_PENDING_BY_TURN: Readonly<Record<string, QueueMutationKind>> = {};\n\nexport type AcceptedQueueSteer = {\n turnId: string;\n triggerEventId: string;\n text: string;\n annotations: SessionTurn[\"annotations\"];\n resources: SessionTurn[\"resources\"];\n tools: SessionTurn[\"tools\"];\n occurredAt: string;\n state: \"sending\" | \"queued\";\n};\n\nexport type UseTurnQueueOptions = EmbeddedSessionClientOverride &\n SessionEventFeedOptions & {\n pollIntervalMs?: number | undefined;\n };\n\nexport type UseTurnQueueResult = {\n snapshot: SessionQueueSnapshot | null;\n /** Human/API prompts exactly in server execution order. Never client-sorted. */\n queue: SessionTurn[];\n /** Canonical pending machine inputs. Events only trigger an authoritative refresh. */\n pendingInputs: SessionPendingInputPreview[];\n /** Exact pending members projected to join an already-waiting prompt. */\n pendingInputAttachment: SessionQueueSnapshot[\"pendingInputAttachment\"];\n /** Secret-safe personal MCP summaries frozen on the exact active turn. */\n activePersonalConnections: McpPersonalConnectionSummary[];\n effectiveControl: EffectiveSessionControl | null;\n /** The latest interrupted attempt has not yet durably proved physical quiescence. */\n stoppingPreviousAttempt: boolean;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n moveTurn: (turnId: string, beforeTurnId: string | null) => Promise<boolean>;\n /** Atomically withdraw a waiting prompt into the private durable composer draft. */\n editTurn: (\n turnId: string,\n options: { expectedDraftRevision: number; replaceDraft: boolean },\n ) => Promise<ComposerDraft | null>;\n /** Advance the same durable waiting prompt; no duplicate prompt is created. */\n steerTurn: (turnId: string) => Promise<boolean>;\n removeTurn: (turnId: string) => Promise<boolean>;\n pendingByTurn: Readonly<Record<string, QueueMutationKind>>;\n mutationFor: (turnId: string) => QueueMutationKind | null;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n /** Immediate chat bridge while the durable Steer event catches up over SSE. */\n acceptedSteers?: AcceptedQueueSteer[] | undefined;\n};\n\n/**\n * The one authoritative human prompt queue. Every mutation carries the exact\n * server versions the operator saw and accepts only monotonic snapshots. A\n * conflict immediately reloads server truth; the client never invents order.\n */\nexport function useTurnQueue(\n sessionId: string | null | undefined,\n options: UseTurnQueueOptions = {},\n): UseTurnQueueResult {\n const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } =\n useEmbeddedSession(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n const pageLive = usePageLiveActivity();\n const [snapshot, setSnapshot] = useState<SessionQueueSnapshot | null>(null);\n const [stateTargetKey, setStateTargetKey] = useState(targetKey);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const [mutationError, setMutationError] = useState<Error | null>(null);\n const [pendingByTurn, setPendingByTurn] = useState<Record<string, QueueMutationKind>>({});\n const [acceptedSteers, setAcceptedSteers] = useState<AcceptedQueueSteer[]>([]);\n const pendingRef = useRef<Record<string, QueueMutationKind>>({});\n const readGeneration = useRef(0);\n const targetKeyRef = useRef(targetKey);\n const snapshotRef = useRef<SessionQueueSnapshot | null>(null);\n\n // Revoke the old target only when the new one commits. A concurrent render\n // may suspend while the previous target remains visible and interactive.\n useLayoutEffect(() => {\n if (targetKeyRef.current === targetKey) return;\n targetKeyRef.current = targetKey;\n readGeneration.current += 1;\n snapshotRef.current = null;\n pendingRef.current = {};\n setStateTargetKey(targetKey);\n setSnapshot(null);\n setLoading(enabled);\n setError(null);\n setMutationError(null);\n setPendingByTurn({});\n setAcceptedSteers([]);\n }, [enabled, targetKey]);\n\n useEffect(() => {\n if (acceptedSteers.length === 0 || options.events === undefined) return;\n const durablyStartedTurnIds = new Set(\n options.events.flatMap((event) =>\n event.type === \"turn.started\" && event.turnId ? [event.turnId] : [],\n ),\n );\n if (durablyStartedTurnIds.size === 0) return;\n // steer_requested can reach the browser before the timeline projection\n // that moves the queued user.message into chat. Keep this bridge through\n // physical cancellation; turn.started is the first boundary at which the\n // replacement timeline must already be visible.\n setAcceptedSteers((current) =>\n current.filter((steer) => !durablyStartedTurnIds.has(steer.turnId)),\n );\n }, [acceptedSteers.length, options.events]);\n\n const acceptSnapshot = useCallback(\n (ownedTargetKey: string, next: SessionQueueSnapshot | null): boolean => {\n if (targetKeyRef.current !== ownedTargetKey) return false;\n const current = snapshotRef.current;\n if (\n next &&\n current &&\n (next.version < current.version ||\n next.effectiveControl.controlVersion < current.effectiveControl.controlVersion)\n ) {\n return false;\n }\n snapshotRef.current = next;\n setStateTargetKey(ownedTargetKey);\n setSnapshot(next);\n return true;\n },\n [],\n );\n\n const load = useCallback(\n async (rejectOnFailure = false): Promise<void> => {\n if (!sessionId) return;\n const ownedTargetKey = `${workspaceId}\\u0000${sessionId}`;\n const ticket = ++readGeneration.current;\n try {\n const fetched = await client.getQueue(workspaceId, sessionId);\n if (targetKeyRef.current !== ownedTargetKey) return;\n const ownsLatestRead = ticket === readGeneration.current;\n if (rejectOnFailure) {\n const committed = acceptSnapshot(ownedTargetKey, fetched);\n if (!committed && !queueSnapshotCovers(snapshotRef.current, fetched)) {\n throw new TypeError(\"Queue reconciliation did not commit authoritative state\");\n }\n setError(null);\n if (ownsLatestRead) setLoading(false);\n } else if (ownsLatestRead) {\n acceptSnapshot(ownedTargetKey, fetched);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (\n targetKeyRef.current === ownedTargetKey &&\n (ticket === readGeneration.current || rejectOnFailure)\n ) {\n setError(asError(cause));\n if (ticket === readGeneration.current) setLoading(false);\n }\n if (rejectOnFailure) throw cause;\n }\n },\n [client, workspaceId, sessionId, acceptSnapshot],\n );\n\n useEffect(() => {\n if (!enabled || !pageLive) {\n setLoading(false);\n return;\n }\n setLoading(true);\n const pollIntervalMs = options.pollIntervalMs;\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n void load();\n return () => {\n readGeneration.current += 1;\n };\n }\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const schedule = () => {\n if (cancelled) return;\n timer = setTimeout(() => {\n timer = null;\n void load().finally(schedule);\n }, pollIntervalMs);\n };\n void load().finally(schedule);\n return () => {\n cancelled = true;\n if (timer !== null) clearTimeout(timer);\n readGeneration.current += 1;\n };\n }, [load, enabled, pageLive, options.pollIntervalMs]);\n\n useEffect(() => {\n if (enabled && workspaceControlEvent) void load();\n }, [enabled, load, workspaceControlEvent]);\n useEffect(() => {\n if (!sessionId || !enabled) return;\n return registerSessionReconciler(sessionId, \"queue\", load);\n }, [enabled, load, registerSessionReconciler, sessionId]);\n\n const scheduleRefresh = useDebouncedCallback(() => void load());\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n isTurnQueueEvent,\n scheduleRefresh,\n {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n },\n async () => await load(true),\n );\n\n const mutate = useCallback(\n async (\n turnId: string,\n kind: QueueMutationKind,\n command: (\n current: SessionQueueSnapshot,\n turn: SessionTurn,\n clientEventId: string,\n ) => Promise<SessionQueueMutationResponse>,\n ): Promise<SessionQueueMutationResponse | null> => {\n const ownedTargetKey = targetKey;\n if (!sessionId || targetKeyRef.current !== ownedTargetKey || pendingRef.current[turnId]) {\n return null;\n }\n const current = snapshotRef.current;\n const turn = current?.items.find((candidate) => candidate.id === turnId);\n if (!current || !turn) return null;\n pendingRef.current = { ...pendingRef.current, [turnId]: kind };\n setStateTargetKey(ownedTargetKey);\n setPendingByTurn(pendingRef.current);\n setMutationError(null);\n const clientEventId = operationKey();\n try {\n let result: SessionQueueMutationResponse;\n try {\n result = await command(current, turn, clientEventId);\n } catch (cause) {\n if (!isOutcomeUnknownError(cause)) throw cause;\n // Same-key replay is a fact check against the durable receipt. It\n // cannot duplicate the command even if the first response was lost.\n result = await command(current, turn, clientEventId);\n }\n if (targetKeyRef.current !== ownedTargetKey) return null;\n acceptSnapshot(ownedTargetKey, result.snapshot);\n return result;\n } catch (cause) {\n if (targetKeyRef.current === ownedTargetKey) {\n setMutationError(asError(cause));\n await load();\n }\n return null;\n } finally {\n if (targetKeyRef.current === ownedTargetKey && turnId in pendingRef.current) {\n const next = { ...pendingRef.current };\n delete next[turnId];\n pendingRef.current = next;\n setPendingByTurn(next);\n }\n }\n },\n [acceptSnapshot, load, sessionId, targetKey],\n );\n\n const moveTurn = useCallback(\n async (turnId: string, beforeTurnId: string | null): Promise<boolean> => {\n const result = await mutate(turnId, \"move\", (current, _turn, clientEventId) =>\n client.moveQueueItem(workspaceId, sessionId!, turnId, {\n clientEventId,\n expectedQueueVersion: current.version,\n beforeTurnId,\n }),\n );\n return result !== null;\n },\n [client, mutate, sessionId, workspaceId],\n );\n\n const editTurn = useCallback(\n async (\n turnId: string,\n edit: { expectedDraftRevision: number; replaceDraft: boolean },\n ): Promise<ComposerDraft | null> => {\n const result = await mutate(turnId, \"edit\", (_current, turn, clientEventId) =>\n client.editQueueItem(workspaceId, sessionId!, turnId, {\n clientEventId,\n expectedTurnVersion: turn.version,\n expectedDraftRevision: edit.expectedDraftRevision,\n replaceDraft: edit.replaceDraft,\n }),\n );\n return result?.draft ?? null;\n },\n [client, mutate, sessionId, workspaceId],\n );\n\n const steerTurn = useCallback(\n async (turnId: string): Promise<boolean> => {\n const ownedTargetKey = targetKey;\n const turn = snapshotRef.current?.items.find((candidate) => candidate.id === turnId);\n if (targetKeyRef.current !== ownedTargetKey) return false;\n if (!turn) {\n setMutationError(new Error(\"That queued prompt changed before Steer could be sent.\"));\n await load();\n return false;\n }\n const optimistic: AcceptedQueueSteer = {\n turnId: turn.id,\n triggerEventId: turn.triggerEventId,\n text: turn.prompt,\n annotations: turn.annotations ?? [],\n resources: turn.resources,\n tools: turn.tools,\n occurredAt: new Date().toISOString(),\n state: \"sending\",\n };\n setAcceptedSteers((current) => [\n ...current.filter((steer) => steer.turnId !== turnId),\n optimistic,\n ]);\n const result = await mutate(turnId, \"steer\", (current, queuedTurn, clientEventId) =>\n client.steerQueueItem(workspaceId, sessionId!, turnId, {\n clientEventId,\n expectedTurnVersion: queuedTurn.version,\n controlEtag: current.effectiveControl.controlEtag,\n }),\n );\n if (targetKeyRef.current !== ownedTargetKey) return false;\n // The active turn can finish while the operator clicks Steer. In that\n // race the queued prompt is atomically claimed before the steer command,\n // so the command conflicts but the user's prompt already advanced into\n // chat. Reconciled absence is success, not a scary unknown-outcome lie.\n const advancedWithoutSteer =\n result === null &&\n snapshotRef.current !== null &&\n !snapshotRef.current.items.some((candidate) => candidate.id === turnId);\n if (advancedWithoutSteer) {\n setMutationError(null);\n setAcceptedSteers((current) => current.filter((steer) => steer.turnId !== turnId));\n return true;\n }\n const accepted =\n result !== null ||\n snapshotRef.current?.items.some(\n (candidate) => candidate.id === turnId && candidate.metadata.delivery === \"steer\",\n ) === true;\n setAcceptedSteers((current) =>\n accepted\n ? current.map((steer) =>\n steer.turnId === turnId ? { ...steer, state: \"queued\" as const } : steer,\n )\n : current.filter((steer) => steer.turnId !== turnId),\n );\n return accepted;\n },\n [client, load, mutate, sessionId, targetKey, workspaceId],\n );\n\n const removeTurn = useCallback(\n async (turnId: string): Promise<boolean> => {\n const result = await mutate(turnId, \"delete\", (_current, turn, clientEventId) =>\n client.deleteQueueItem(workspaceId, sessionId!, turnId, {\n clientEventId,\n expectedTurnVersion: turn.version,\n reason: \"Deleted from the prompt queue\",\n }),\n );\n return result !== null;\n },\n [client, mutate, sessionId, workspaceId],\n );\n\n const identityMatches = stateTargetKey === targetKey;\n const visibleSnapshot = identityMatches ? snapshot : null;\n const visiblePendingByTurn = identityMatches ? pendingByTurn : EMPTY_PENDING_BY_TURN;\n const mutating = useMemo(\n () => Object.keys(visiblePendingByTurn).length > 0,\n [visiblePendingByTurn],\n );\n const mutationFor = useCallback(\n (turnId: string): QueueMutationKind | null => visiblePendingByTurn[turnId] ?? null,\n [visiblePendingByTurn],\n );\n\n return {\n snapshot: visibleSnapshot,\n queue: visibleSnapshot?.items ?? [],\n pendingInputs: visibleSnapshot?.pendingInputs ?? [],\n pendingInputAttachment: visibleSnapshot?.pendingInputAttachment ?? null,\n activePersonalConnections: visibleSnapshot?.activePersonalConnections ?? [],\n effectiveControl: visibleSnapshot?.effectiveControl ?? null,\n stoppingPreviousAttempt: visibleSnapshot?.stoppingPreviousAttempt ?? false,\n loading: identityMatches ? loading : enabled,\n error: identityMatches ? error : null,\n refresh: load,\n moveTurn,\n editTurn,\n steerTurn,\n removeTurn,\n pendingByTurn: visiblePendingByTurn,\n mutationFor,\n mutating,\n mutationError: identityMatches ? mutationError : null,\n clearMutationError: useCallback(() => {\n if (targetKeyRef.current === targetKey) setMutationError(null);\n }, [targetKey]),\n acceptedSteers: identityMatches ? acceptedSteers : [],\n };\n}\n\nfunction operationKey(): string {\n return globalThis.crypto.randomUUID();\n}\n\nfunction asError(cause: unknown): Error {\n return normalizeError(cause);\n}\n\nfunction isOutcomeUnknownError(cause: unknown): boolean {\n return (\n typeof cause === \"object\" &&\n cause !== null &&\n (cause as { outcomeUnknown?: unknown }).outcomeUnknown === true\n );\n}\n","import type {\n SessionEvent,\n SessionHumanInputRequest,\n SubmitHumanInputResponseRequest,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n useEmbeddedHumanInputSession,\n type EmbeddedHumanInputClientOverride,\n} from \"../session-context\";\nimport { isActionableHumanInputRequest } from \"../human-input\";\nimport {\n useDebouncedCallback,\n useMutationRunner,\n usePolledValue,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\n/** Events that can create, settle, or invalidate an actionable request. */\nexport function isHumanInputEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return (\n event.type === \"session.humanInput.requested\" ||\n event.type === \"user.humanInputResponse\" ||\n event.type === \"turn.completed\" ||\n event.type === \"turn.failed\" ||\n event.type === \"turn.cancelled\"\n );\n}\n\nexport type UseHumanInputRequestsOptions = EmbeddedHumanInputClientOverride &\n SessionEventFeedOptions & {\n /** Optional safety-net polling. Durable events drive refresh by default. */\n pollIntervalMs?: number | undefined;\n };\n\nexport type UseHumanInputRequestsResult = {\n requests: SessionHumanInputRequest[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n respond: (\n requestId: string,\n response: SubmitHumanInputResponseRequest,\n ) => Promise<SessionEvent | null>;\n respondingRequestId: string | null;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Authoritative structured-human-input hook. The server's pending-request\n * table is the read model; events only trigger reconciliation. This lets an\n * embedded host use the same primitive with a shared event feed or its own SDK\n * proxy without rebuilding request lifecycle logic.\n */\nexport function useHumanInputRequests(\n sessionId: string | null | undefined,\n options: UseHumanInputRequestsOptions = {},\n): UseHumanInputRequestsResult {\n const { client, workspaceId, registerSessionReconciler } = useEmbeddedHumanInputSession(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const load = useCallback(\n async (): Promise<SessionHumanInputRequest[]> =>\n sessionId\n ? await client.listHumanInputRequests(workspaceId, sessionId, { status: \"pending\" })\n : [],\n [client, sessionId, workspaceId],\n );\n const state = usePolledValue(load, {\n enabled,\n pollIntervalMs: options.pollIntervalMs,\n });\n const loadedRequests = state.data;\n const refreshRequests = state.refresh;\n const mutation = useMutationRunner(`${workspaceId}\\u0000${sessionId ?? \"\"}`);\n const [respondingRequestId, setRespondingRequestId] = useState<string | null>(null);\n const [deadlineVersion, setDeadlineVersion] = useState(0);\n const respondingRequestRef = useRef<string | null>(null);\n\n useEffect(() => {\n respondingRequestRef.current = null;\n setRespondingRequestId(null);\n }, [sessionId, workspaceId]);\n useEffect(() => {\n if (!sessionId || !enabled) return;\n return registerSessionReconciler(sessionId, \"human-input\", state.refresh);\n }, [enabled, registerSessionReconciler, sessionId, state.refresh]);\n\n const scheduleRefresh = useDebouncedCallback(() => void state.refresh());\n useSessionEventTrigger(client, workspaceId, sessionId, isHumanInputEvent, scheduleRefresh, {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n });\n\n useEffect(() => {\n const now = Date.now();\n const nextDeadline = (loadedRequests ?? []).reduce<number | null>((next, request) => {\n if (request.status !== \"pending\" || !request.expiresAt) return next;\n const deadline = Date.parse(request.expiresAt);\n if (!Number.isFinite(deadline) || deadline <= now) return next;\n return next === null ? deadline : Math.min(next, deadline);\n }, null);\n if (nextDeadline === null) return;\n const timer = globalThis.setTimeout(\n () => {\n setDeadlineVersion((current) => current + 1);\n void refreshRequests();\n },\n Math.min(2_147_483_647, Math.max(0, nextDeadline - now + 1)),\n );\n return () => globalThis.clearTimeout(timer);\n }, [loadedRequests, refreshRequests]);\n\n const respond = useCallback(\n async (\n requestId: string,\n response: SubmitHumanInputResponseRequest,\n ): Promise<SessionEvent | null> => {\n if (!sessionId || respondingRequestRef.current !== null) return null;\n respondingRequestRef.current = requestId;\n setRespondingRequestId(requestId);\n try {\n const event = await mutation.run(() =>\n client.submitHumanInputResponse(workspaceId, sessionId, requestId, response, {\n clientEventId: globalThis.crypto.randomUUID(),\n }),\n );\n if (event) await state.refresh();\n return event;\n } finally {\n if (respondingRequestRef.current === requestId) {\n respondingRequestRef.current = null;\n setRespondingRequestId(null);\n }\n }\n },\n [client, mutation, sessionId, state, workspaceId],\n );\n\n const now = Date.now();\n void deadlineVersion;\n return {\n requests: [...(state.data ?? [])]\n .filter((request) => isActionableHumanInputRequest(request, now))\n .sort(\n (left, right) =>\n left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id),\n ),\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n respond,\n respondingRequestId,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type { FileAsset, FileResourceRef } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n useEmbeddedFileAttachments,\n type EmbeddedFileAttachmentClientOverride,\n} from \"../session-context\";\nimport { useErrorMessage } from \"../lib/error-message\";\n\nexport type UseFileAttachmentsOptions = EmbeddedFileAttachmentClientOverride & {\n /**\n * Only files matching this predicate are accepted by {@link\n * UseFileAttachmentsResult.addFromPaste} (the clipboard path). Defaults to\n * `image/*` — the console's historical paste filter. {@link\n * UseFileAttachmentsResult.addFiles} (the explicit picker / drop path)\n * bypasses it.\n */\n /** Retain original uploads in the chat owner’s personal scope when private. */\n scope?: \"workspace\" | \"personal\";\n pasteFilter?: ((file: File) => boolean) | undefined;\n};\n\nexport type FileAttachment = {\n id: string;\n name: string;\n contentType: string;\n sizeBytes: number;\n status: \"uploading\" | \"ready\" | \"failed\";\n /** The SDK `FileAsset` once the upload finishes. */\n file?: FileAsset | undefined;\n /** Object-URL for an inline preview; minted for `image/*` files only. */\n previewUrl?: string | undefined;\n /** Stable SDK failure code for UI behavior that must not parse error copy. */\n errorCode?: \"secure_context_required\" | undefined;\n error?: string | undefined;\n /** Original diagnostic failure; presentation copy is kept separately in `error`. */\n errorCause?: unknown;\n};\n\nexport type UseFileAttachmentsResult = {\n attachments: FileAttachment[];\n /**\n * `FileResourceRef[]` for every attachment that finished uploading — feed\n * straight into `useComposer`'s `sendExtras.resources`.\n */\n readyResources: FileResourceRef[];\n /** True while any attachment is still uploading (drives progress UI). */\n uploading: boolean;\n /**\n * True while any attachment still needs an explicit outcome: wait for an\n * upload, retry a failure, or remove it. This is the loss-prevention send\n * gate; failed cards must never be silently omitted from a message.\n */\n hasUnresolved: boolean;\n /** Explicit picker / drop path — uploads every file, no filter. */\n addFiles: (files: Iterable<File>) => void;\n /** Clipboard path — applies `pasteFilter` (default `image/*`) then uploads. */\n addFromPaste: (event: { clipboardData: DataTransfer | null }) => void;\n /** Restore already-ready server assets without recreating browser-local bytes. */\n restoreReadyFiles: (files: Iterable<FileAsset>) => void;\n /**\n * Resolve a ready image's short-lived server preview URL on demand. Optional\n * for upload-only embedded clients; local object-URL previews remain usable\n * without it.\n */\n loadPreview?: ((id: string, signal?: AbortSignal) => Promise<string | undefined>) | undefined;\n /**\n * Re-run the upload for a `failed` attachment, in place (same id, same\n * source file). No-op for an id that isn't a known failed upload.\n */\n retry: (id: string) => void;\n /**\n * Keep an attachment's object-URL alive for a consumer that outlives its\n * queue entry (for example, an open route-level lightbox). The returned\n * release is idempotent; pending revocation finishes after the last holder\n * releases. Returns `undefined` when the attachment has no local preview.\n */\n retainPreview: (id: string) => (() => void) | undefined;\n /** Remove one attachment; revokes its object-URL after retained users finish. */\n remove: (id: string) => void;\n /**\n * Remove only finalized files whose durable ids were accepted by a send.\n * Attachments added while that request was in flight remain queued for the\n * next message.\n */\n removeReadyFiles: (fileIds: Iterable<string>) => void;\n /** Remove all attachments and revoke every unretained object-URL. */\n clear: () => void;\n};\n\nconst isImage = (file: File): boolean => file.type.startsWith(\"image/\");\n\nlet fallbackAttachmentId = 0;\n\nfunction createAttachmentId(): string {\n const cryptoSource = globalThis.crypto;\n if (typeof cryptoSource?.randomUUID === \"function\") return cryptoSource.randomUUID();\n fallbackAttachmentId += 1;\n // This id is only a browser-local React key and retry lookup, never durable\n // authority. Keep attachment tracking usable when HTTP withholds randomUUID\n // or Web Crypto is unavailable so the SDK's typed failure reaches the card.\n return `attachment:${Date.now().toString(36)}:${fallbackAttachmentId.toString(36)}`;\n}\n\nfunction secureContextRequiredErrorCode(error: unknown): \"secure_context_required\" | undefined {\n return typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"secure_context_required\"\n ? error.code\n : undefined;\n}\n\n/**\n * Upload-and-track state for files attached to the next message. Owns the\n * full client-side upload layer: a per-file `uploading | ready | failed`\n * status machine driven by the SDK's `client.uploadFile`, object-URL image\n * previews with create/revoke lifecycle, the `image/*` clipboard paste filter,\n * and a `FileResourceRef[]` projection that drops straight into a message's\n * `resources`. Workspace-scoped, so it resolves both client and workspace from\n * the {@link OpenGeniProvider} (or a per-call `{ client, workspaceId }`).\n */\nexport function useFileAttachments(\n options: UseFileAttachmentsOptions = {},\n): UseFileAttachmentsResult {\n const { client, workspaceId } = useEmbeddedFileAttachments(options);\n const formatError = useErrorMessage();\n const pasteFilter = options.pasteFilter ?? isImage;\n const [attachments, setAttachments] = useState<FileAttachment[]>([]);\n const attachmentsRef = useRef(attachments);\n attachmentsRef.current = attachments;\n // Keep the source File per attachment id so a failed upload can be retried\n // in place. Cleared on remove/clear so it never outlives its attachment.\n const sources = useRef<Map<string, File>>(new Map());\n // Object URLs must be owned synchronously: React may discard an attachment\n // state update when its component unmounts in the same batch that minted the\n // preview. The registry remains available to cleanup even before a render.\n const previewUrls = useRef<Map<string, string>>(new Map());\n const previewRetainers = useRef<Map<string, number>>(new Map());\n const pendingPreviewRevocations = useRef<Set<string>>(new Set());\n const revokePreview = useCallback((id: string) => {\n const previewUrl = previewUrls.current.get(id);\n if (!previewUrl) return;\n if ((previewRetainers.current.get(id) ?? 0) > 0) {\n pendingPreviewRevocations.current.add(id);\n return;\n }\n previewUrls.current.delete(id);\n pendingPreviewRevocations.current.delete(id);\n URL.revokeObjectURL(previewUrl);\n }, []);\n const revokeAllPreviews = useCallback(() => {\n for (const id of previewUrls.current.keys()) revokePreview(id);\n }, [revokePreview]);\n const retainPreview = useCallback(\n (id: string): (() => void) | undefined => {\n if (!previewUrls.current.has(id)) return undefined;\n previewRetainers.current.set(id, (previewRetainers.current.get(id) ?? 0) + 1);\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const remaining = (previewRetainers.current.get(id) ?? 1) - 1;\n if (remaining > 0) {\n previewRetainers.current.set(id, remaining);\n return;\n }\n previewRetainers.current.delete(id);\n if (pendingPreviewRevocations.current.has(id)) revokePreview(id);\n };\n },\n [revokePreview],\n );\n // Ready-file reconciliation uses functional state updaters, which React may\n // evaluate during a concurrent render that later suspends or is abandoned.\n // Diff only committed attachment sets here so URL revocation cannot run from\n // render-phase code while the previously committed DOM still uses a preview.\n const committedAttachmentIds = useRef<Set<string>>(new Set());\n useEffect(() => {\n const currentIds = new Set(attachments.map((attachment) => attachment.id));\n for (const id of committedAttachmentIds.current) {\n if (!currentIds.has(id)) revokePreview(id);\n }\n committedAttachmentIds.current = currentIds;\n }, [attachments, revokePreview]);\n // Upload promises are not cancellable at this layer. Fence their settlements\n // when the hook changes client/workspace or unmounts so an old tenant/session\n // cannot mutate the next attachment queue (or an already-unmounted component).\n const scopeGeneration = useRef(0);\n const previousScope = useRef({ client, workspaceId });\n\n useEffect(() => {\n const previous = previousScope.current;\n if (previous.client === client && previous.workspaceId === workspaceId) return;\n previousScope.current = { client, workspaceId };\n scopeGeneration.current += 1;\n sources.current.clear();\n revokeAllPreviews();\n setAttachments([]);\n }, [client, revokeAllPreviews, workspaceId]);\n\n useEffect(\n () => () => {\n scopeGeneration.current += 1;\n sources.current.clear();\n revokeAllPreviews();\n },\n [revokeAllPreviews],\n );\n\n // Run (or re-run) the upload for one already-tracked attachment id. Sets it\n // back to `uploading`, then resolves to `ready` (with the asset) or `failed`\n // (with the error message).\n const startUpload = useCallback(\n (id: string, file: File) => {\n const generation = scopeGeneration.current;\n void client\n .uploadFile(workspaceId, {\n filename: file.name || \"file\",\n contentType: file.type || \"application/octet-stream\",\n data: file,\n ...(options.scope ? { scope: options.scope } : {}),\n })\n .then((asset) => {\n if (scopeGeneration.current !== generation) return;\n // Retry bytes are useful only until durable finalization succeeds.\n // Drop the source File immediately; restored/ready attachments must\n // never retain browser-local byte authority.\n sources.current.delete(id);\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? {\n ...attachment,\n status: \"ready\",\n file: asset,\n name: asset.filename,\n contentType: asset.contentType,\n sizeBytes: asset.sizeBytes,\n errorCode: undefined,\n error: undefined,\n errorCause: undefined,\n }\n : attachment,\n ),\n );\n })\n .catch((error: unknown) => {\n if (scopeGeneration.current !== generation) return;\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? {\n ...attachment,\n status: \"failed\",\n errorCode: secureContextRequiredErrorCode(error),\n error: formatError(error),\n errorCause: error,\n }\n : attachment,\n ),\n );\n });\n },\n [client, workspaceId, options.scope, formatError],\n );\n\n const addFiles = useCallback(\n (files: Iterable<File>) => {\n for (const file of files) {\n const id = createAttachmentId();\n sources.current.set(id, file);\n const previewUrl = isImage(file) ? URL.createObjectURL(file) : undefined;\n if (previewUrl) previewUrls.current.set(id, previewUrl);\n setAttachments((current) => [\n ...current,\n {\n id,\n name: file.name || \"image\",\n contentType: file.type || \"application/octet-stream\",\n sizeBytes: file.size,\n status: \"uploading\",\n ...(previewUrl ? { previewUrl } : {}),\n },\n ]);\n startUpload(id, file);\n }\n },\n [startUpload],\n );\n\n const retry = useCallback(\n (id: string) => {\n const file = sources.current.get(id);\n if (!file) {\n return;\n }\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? {\n ...attachment,\n status: \"uploading\",\n errorCode: undefined,\n error: undefined,\n errorCause: undefined,\n }\n : attachment,\n ),\n );\n startUpload(id, file);\n },\n [startUpload],\n );\n\n const addFromPaste = useCallback(\n (event: { clipboardData: DataTransfer | null }) => {\n const clipboardFiles = event.clipboardData?.files;\n if (!clipboardFiles) {\n return;\n }\n const files = [...clipboardFiles].filter(pasteFilter);\n if (files.length > 0) {\n addFiles(files);\n }\n },\n [addFiles, pasteFilter],\n );\n\n const restoreReadyFiles = useCallback(\n (files: Iterable<FileAsset>) => {\n const incoming = new Map<string, FileAsset>();\n for (const file of files) {\n if (file.status === \"ready\" && file.workspaceId === workspaceId) {\n incoming.set(file.id, file);\n }\n }\n setAttachments((current) => {\n const unresolved = current.filter((attachment) => attachment.status !== \"ready\");\n const existingReady = new Map(\n current.flatMap((attachment) =>\n attachment.status === \"ready\" && attachment.file\n ? ([[attachment.file.id, attachment]] as const)\n : [],\n ),\n );\n const restored = [...incoming.values()].map((file): FileAttachment => {\n const existing = existingReady.get(file.id);\n return existing\n ? {\n ...existing,\n name: file.filename,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n status: \"ready\",\n file,\n errorCode: undefined,\n error: undefined,\n errorCause: undefined,\n }\n : {\n id: `restored:${file.id}`,\n name: file.filename,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n status: \"ready\",\n file,\n // No source File and no object URL: server metadata is the\n // only authority restored across page/device boundaries.\n };\n });\n // A server restoration is authoritative for finalized assets, but an\n // upload that has not finalized still belongs to the local actor. Keep\n // those unresolved entries while replacing the ready set exactly.\n return [...unresolved, ...restored];\n });\n },\n [workspaceId],\n );\n\n const loadPreview = useCallback(\n async (id: string, signal?: AbortSignal): Promise<string | undefined> => {\n const generation = scopeGeneration.current;\n const attachment = attachmentsRef.current.find((candidate) => candidate.id === id);\n const createDownloadUrl = client.createFileDownloadUrl;\n if (\n !attachment ||\n attachment.status !== \"ready\" ||\n !attachment.file ||\n !attachment.contentType.startsWith(\"image/\") ||\n typeof createDownloadUrl !== \"function\" ||\n signal?.aborted\n ) {\n return undefined;\n }\n const fileId = attachment.file.id;\n const signed = await createDownloadUrl.call(client, workspaceId, fileId, { signal });\n if (scopeGeneration.current !== generation || signal?.aborted) return undefined;\n const current = attachmentsRef.current.find((candidate) => candidate.id === id);\n if (current?.status !== \"ready\" || current.file?.id !== fileId) return undefined;\n return signed.url;\n },\n [client, workspaceId],\n );\n\n const remove = useCallback(\n (id: string) => {\n sources.current.delete(id);\n revokePreview(id);\n setAttachments((current) => current.filter((attachment) => attachment.id !== id));\n },\n [revokePreview],\n );\n\n const removeReadyFiles = useCallback((fileIds: Iterable<string>) => {\n const accepted = new Set(fileIds);\n if (accepted.size === 0) return;\n setAttachments((current) =>\n current.filter((attachment) => {\n return !(\n attachment.status === \"ready\" &&\n attachment.file !== undefined &&\n accepted.has(attachment.file.id)\n );\n }),\n );\n }, []);\n\n const clear = useCallback(() => {\n sources.current.clear();\n revokeAllPreviews();\n setAttachments([]);\n }, [revokeAllPreviews]);\n\n return {\n attachments,\n readyResources: attachments.flatMap((attachment): FileResourceRef[] =>\n attachment.status === \"ready\" && attachment.file\n ? [{ kind: \"file\", fileId: attachment.file.id }]\n : [],\n ),\n uploading: attachments.some((attachment) => attachment.status === \"uploading\"),\n hasUnresolved: attachments.some((attachment) => attachment.status !== \"ready\"),\n addFiles,\n addFromPaste,\n restoreReadyFiles,\n ...(typeof client.createFileDownloadUrl === \"function\" ? { loadPreview } : {}),\n retry,\n retainPreview,\n remove,\n removeReadyFiles,\n clear,\n };\n}\n","import type { SessionControlResponse, SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\nimport { useEmbeddedSession, type EmbeddedSessionClientOverride } from \"../session-context\";\nimport { useMutationRunner } from \"./internal\";\n\nexport type UseSessionControlOptions = EmbeddedSessionClientOverride;\n\nexport type UseSessionControlResult = {\n pause: (reason?: string) => Promise<SessionControlResponse | null>;\n resume: (reason?: string) => Promise<SessionControlResponse | null>;\n controlling: boolean;\n /** Approve a pending `requires_action` approval. */\n approve: (approvalId: string, message?: string) => Promise<SessionEvent | null>;\n /** Reject a pending `requires_action` approval. */\n reject: (approvalId: string, message?: string) => Promise<SessionEvent | null>;\n /** True while an approval decision is in flight. */\n responding: boolean;\n error: Error | null;\n clearError: () => void;\n};\n\n/**\n * Session pause/resume and approval decisions. Pair with\n * `useSessionEvents` (for `session.requiresAction` payloads carrying the\n * `approvalId`) to render an approval bar.\n */\nexport function useSessionControl(\n sessionId: string | null | undefined,\n options: UseSessionControlOptions = {},\n): UseSessionControlResult {\n const { client, workspaceId } = useEmbeddedSession(options);\n const approvalTargetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n const pendingApproval = useRef<{\n targetKey: string;\n decisionKey: string;\n clientEventId: string;\n } | null>(null);\n useLayoutEffect(() => {\n if (pendingApproval.current?.targetKey !== approvalTargetKey) {\n pendingApproval.current = null;\n }\n }, [approvalTargetKey]);\n const {\n run: runControl,\n mutating: controlling,\n mutationError: controlError,\n clearMutationError: clearControlError,\n } = useMutationRunner(approvalTargetKey);\n const {\n run: runApproval,\n mutating: responding,\n mutationError: approvalError,\n clearMutationError: clearApprovalError,\n } = useMutationRunner(approvalTargetKey);\n\n const pause = useCallback(\n async (reason?: string): Promise<SessionControlResponse | null> => {\n if (!sessionId) {\n return null;\n }\n return await runControl(() =>\n client.pauseSession(workspaceId, sessionId, reason !== undefined ? { reason } : {}),\n );\n },\n [client, workspaceId, sessionId, runControl],\n );\n\n const resume = useCallback(\n async (reason?: string): Promise<SessionControlResponse | null> => {\n if (!sessionId) return null;\n return await runControl(() =>\n client.resumeSession(workspaceId, sessionId, reason !== undefined ? { reason } : {}),\n );\n },\n [client, workspaceId, sessionId, runControl],\n );\n\n const decide = useCallback(\n async (\n approvalId: string,\n decision: \"approve\" | \"reject\",\n message?: string,\n ): Promise<SessionEvent | null> => {\n if (!sessionId) {\n return null;\n }\n const decisionKey = JSON.stringify([approvalId, decision, message ?? null]);\n if (pendingApproval.current?.decisionKey !== decisionKey) {\n pendingApproval.current = {\n targetKey: approvalTargetKey,\n decisionKey,\n clientEventId: crypto.randomUUID(),\n };\n }\n const clientEventId = pendingApproval.current.clientEventId;\n const accepted = await runApproval(() =>\n client.sendApprovalDecision(workspaceId, sessionId, {\n approvalId,\n decision,\n ...(message !== undefined ? { message } : {}),\n clientEventId,\n }),\n );\n if (\n accepted !== null &&\n pendingApproval.current?.targetKey === approvalTargetKey &&\n pendingApproval.current.clientEventId === clientEventId\n ) {\n pendingApproval.current = null;\n }\n return accepted;\n },\n [approvalTargetKey, client, workspaceId, sessionId, runApproval],\n );\n\n const approve = useCallback(\n async (approvalId: string, message?: string) => await decide(approvalId, \"approve\", message),\n [decide],\n );\n const reject = useCallback(\n async (approvalId: string, message?: string) => await decide(approvalId, \"reject\", message),\n [decide],\n );\n\n const error = approvalError ?? controlError;\n const clearError = useCallback(() => {\n clearControlError();\n clearApprovalError();\n }, [clearControlError, clearApprovalError]);\n\n return {\n pause,\n resume,\n controlling,\n approve,\n reject,\n responding,\n error,\n clearError,\n };\n}\n","import {\n parseToolDisplayMetadata,\n type ToolDisplayMetadata,\n type SessionEvent,\n} from \"@opengeni/sdk\";\n\n/* ----------------------------------------------------------------------------\n Pending-approvals projection\n\n `session.requiresAction` events live forever in the durable log, so a\n console that replays the log from sequence 0 must not render every\n historical approval as actionable. `projectPendingApprovals` folds the\n ordered event log into the approvals that are still undecided *now*:\n\n - `session.requiresAction` replaces the pending set with the payload's\n approvals (the producer always emits the full currently-pending set, so\n re-emission after a worker re-dispatch cannot duplicate cards);\n - `user.approvalDecision` subtracts the decided approval;\n - the owning turn finishing (`turn.completed`/`turn.failed`/\n `turn.cancelled`) clears the set — whatever was pending died with the\n turn. A `turn.cancelled` for a *different* turn (deleting a queued turn\n while the session waits on an approval) leaves the set alone.\n\n Pure function — same events in, same approvals out — so approve-then-reload\n projects to an empty set instead of a zombie Approve button.\n -------------------------------------------------------------------------- */\n\nexport type PendingApproval = {\n /** The id to send back via `user.approvalDecision` (`approvalId`). */\n id: string;\n /** Tool/function name awaiting the decision. */\n name: string;\n display?: ToolDisplayMetadata;\n arguments?: unknown;\n /** The raw approval entry from the `session.requiresAction` payload. */\n raw?: unknown;\n};\n\n/** The approvals carried by one `session.requiresAction` payload. */\nexport function approvalsFromRequiresAction(payload: unknown): PendingApproval[] {\n const approvals =\n payload && typeof payload === \"object\"\n ? (payload as { approvals?: unknown }).approvals\n : undefined;\n if (!Array.isArray(approvals)) {\n return [];\n }\n return approvals.map((approval, index) => {\n const raw = (approval && typeof approval === \"object\" ? approval : {}) as Record<\n string,\n unknown\n >;\n const rawItem =\n raw.rawItem && typeof raw.rawItem === \"object\"\n ? (raw.rawItem as Record<string, unknown>)\n : {};\n const display = parseToolDisplayMetadata(raw.display);\n return {\n // Mirror the runtime's canonical interruption identity before retaining\n // the legacy top-level callId fallback for already-normalized payloads.\n id: String(rawItem.callId ?? rawItem.id ?? raw.id ?? raw.callId ?? raw.name ?? index),\n name: String(raw.name ?? raw.toolName ?? rawItem.name ?? \"approval\"),\n ...(display ? { display } : {}),\n arguments: raw.arguments ?? rawItem.arguments,\n raw: approval,\n };\n });\n}\n\n/** The approvals still awaiting a decision after replaying `events` in order. */\nexport function projectPendingApprovals(events: SessionEvent[]): PendingApproval[] {\n let pending: PendingApproval[] = [];\n let owningTurnId: string | null = null;\n for (const event of events) {\n switch (event.type) {\n case \"session.requiresAction\": {\n pending = approvalsFromRequiresAction(event.payload);\n owningTurnId = event.turnId ?? null;\n break;\n }\n case \"user.approvalDecision\": {\n const payload =\n event.payload && typeof event.payload === \"object\"\n ? (event.payload as { approvalId?: unknown })\n : {};\n if (typeof payload.approvalId === \"string\") {\n pending = pending.filter((approval) => approval.id !== payload.approvalId);\n }\n break;\n }\n case \"turn.completed\":\n case \"turn.failed\":\n case \"turn.cancelled\": {\n // Scope clearing to the turn that raised the approvals when both\n // sides carry a turn id; clear conservatively when either is unknown.\n if (owningTurnId === null || event.turnId == null || event.turnId === owningTurnId) {\n pending = [];\n owningTurnId = null;\n }\n break;\n }\n default:\n break;\n }\n }\n return pending;\n}\n","import type { ComposerState } from \"./hooks/use-composer\";\nimport type { UseTurnQueueResult } from \"./hooks/use-turn-queue\";\nimport type { TimelineItem, UserMessageItem } from \"./timeline/types\";\n\n/** Keep pending prompts in the queue, not duplicated in the conversation. */\nexport function conversationTimeline(\n items: TimelineItem[],\n queue: Pick<UseTurnQueueResult, \"queue\" | \"snapshot\" | \"acceptedSteers\">,\n composer: Pick<\n ComposerState,\n | \"optimisticMessages\"\n | \"retryOptimisticMessage\"\n | \"restoreOptimisticMessage\"\n | \"removeOptimisticMessage\"\n >,\n): TimelineItem[] {\n const queued = new Set(\n queue.queue\n .filter((turn) => turn.metadata.delivery !== \"steer\")\n .map((turn) => turn.triggerEventId),\n );\n const pending = composer.optimisticMessages ?? [];\n const pendingQueue = new Set(\n pending\n .filter(\n (message) =>\n message.destination === \"queue\" &&\n !(\n message.turnId &&\n message.appliedQueueVersion != null &&\n queue.snapshot &&\n queue.snapshot.version >= message.appliedQueueVersion &&\n !queue.queue.some((turn) => turn.id === message.turnId)\n ),\n )\n .map((message) => `user-message:${message.clientEventId}`),\n );\n const visible = items.filter(\n (item) =>\n item.kind !== \"user-message\" ||\n (!queued.has(item.id) && !pendingQueue.has(item.reconciliationKey ?? \"\")),\n );\n const keys = new Set(\n visible.flatMap((item) => (item.kind === \"user-message\" ? [item.reconciliationKey] : [])),\n );\n const optimistic: UserMessageItem[] = pending\n .filter(\n (message) =>\n (message.destination === \"chat\" || message.state === \"failed\") &&\n !keys.has(`user-message:${message.clientEventId}`) &&\n !queue.queue.some((turn) => turn.id === message.turnId),\n )\n .map((message) => ({\n kind: \"user-message\",\n id: `optimistic:${message.clientEventId}`,\n reconciliationKey: `user-message:${message.clientEventId}`,\n text: message.text,\n annotations: message.annotations.map((annotation, ordinal) => ({ ...annotation, ordinal })),\n resources: message.resources,\n tools: [],\n occurredAt: message.occurredAt,\n delivery: {\n state: message.state,\n ...(message.error ? { error: message.error } : {}),\n ...(message.state === \"failed\"\n ? {\n ...(message.retryable !== false && composer.retryOptimisticMessage\n ? { onRetry: () => composer.retryOptimisticMessage?.(message.clientEventId) }\n : {}),\n ...(message.retryable === false && composer.restoreOptimisticMessage\n ? { onEdit: () => composer.restoreOptimisticMessage?.(message.clientEventId) }\n : {}),\n onRemove: () => composer.removeOptimisticMessage?.(message.clientEventId),\n }\n : {}),\n },\n }));\n const ids = new Set(visible.map((item) => item.id));\n const steers: UserMessageItem[] = (queue.acceptedSteers ?? [])\n .filter((steer) => !ids.has(steer.triggerEventId))\n .map((steer) => ({\n kind: \"user-message\",\n id: steer.triggerEventId,\n text: steer.text,\n annotations: steer.annotations,\n resources: steer.resources,\n tools: steer.tools,\n occurredAt: steer.occurredAt,\n delivery: { state: steer.state },\n }));\n return [...visible, ...optimistic, ...steers];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAYO,SAAS,8BACd,SACA,QAAQ,KAAK,IAAI,GACR;AACT,MAAI,QAAQ,WAAW,UAAW,QAAO;AACzC,MAAI,CAAC,QAAQ,UAAW,QAAO;AAC/B,QAAM,WAAW,KAAK,MAAM,QAAQ,SAAS;AAC7C,SAAO,OAAO,SAAS,QAAQ,KAAK,WAAW;AACjD;AAGO,SAAS,2BACd,OACiC;AACjC,MAAI,MAAM,SAAS,kCAAkC,CAAC,SAAS,MAAM,OAAO,EAAG,QAAO;AACtF,QAAM,UAAU,MAAM,QAAQ;AAC9B,MAAI,CAAC,SAAS,OAAO,KAAK,OAAO,QAAQ,OAAO,YAAY,CAAC,MAAM,QAAQ,QAAQ,SAAS,GAAG;AAC7F,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,IAAI,QAAQ;AAAA,IACZ,QAAQ,MAAM,UAAU;AAAA,IACxB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ,cAAc;AAAA,IACjC,WAAW,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY;AAAA,EACzE;AACF;AAQO,SAAS,iCACd,QAC4B;AAC5B,QAAM,UAAU,oBAAI,IAAsC;AAC1D,aAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,2BAA2B,KAAK;AAClD,QAAI,WAAW;AACb,cAAQ,IAAI,UAAU,IAAI,SAAS;AACnC;AAAA,IACF;AACA,QAAI,MAAM,SAAS,6BAA6B,SAAS,MAAM,OAAO,GAAG;AACvE,UAAI,OAAO,MAAM,QAAQ,cAAc,SAAU,SAAQ,OAAO,MAAM,QAAQ,SAAS;AACvF;AAAA,IACF;AACA,QACE,MAAM,SAAS,oBACf,MAAM,SAAS,iBACf,MAAM,SAAS,kBACf;AACA,iBAAW,CAAC,IAAI,OAAO,KAAK,SAAS;AACnC,YACE,QAAQ,WAAW,QACnB,MAAM,WAAW,QACjB,MAAM,WAAW,UACjB,QAAQ,WAAW,MAAM,QACzB;AACA,kBAAQ,OAAO,EAAE;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,CAAC,GAAG,QAAQ,OAAO,CAAC;AAC7B;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;;;ACpDA,IAAI;AACJ,IAAI,+BAA+B;AAG5B,SAAS,2CACd,MACA,SACA,eAAe,OACN;AACT,QAAM,kBAAkB;AACxB,QAAM,uBAAuB;AAC7B,yBAAuB;AACvB,iCAA+B;AAC/B,MAAI;AACF,WAAO,KAAK;AAAA,EACd,UAAE;AACA,2BAAuB;AACvB,mCAA+B;AAAA,EACjC;AACF;AAMO,SAAS,8BACd,MAKyB;AACzB,MAAI;AACJ,MAAI;AACJ,QAAM,SAAS,IAAI,QAAiB,CAAC,SAAS,WAAW;AACvD,oBAAgB;AAChB,mBAAe;AAAA,EACjB,CAAC;AACD,SAAO,YAAY;AACnB,SAAO,gBAAgB;AACvB,yBAAuB,MAAM;AAC7B,MAAI;AACF,UAAM,SAAS;AAAA,MACb,MAAM;AACJ,eAAO,YAAY;AAAA,MACrB;AAAA,MACA;AAAA,MACA,MAAM;AACJ,eAAO,gBAAgB;AAAA,MACzB;AAAA,IACF;AACA,YAAQ,QAAQ,MAAM,EAAE,KAAK,eAAe,YAAY;AAAA,EAC1D,SAAS,OAAO;AACd,iBAAa,KAAK;AAAA,EACpB;AACA,SAAO;AACT;;;ACtFA;AAAA,EACE;AAAA,OAIK;AACP,SAAS,iBAAiB,aAAa,WAAW,SAAS,QAAQ,gBAAgB;AAwFnF,IAAM,4BAA4B;AAClC,IAAM,oBAAoB;AAC1B,IAAM,qBAAqB;AAC3B,IAAM,kBAAkB;AACxB,IAAM,qBAAqB;AAC3B,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAC5B,IAAM,mBAAmB;AAIzB,IAAM,oBAAoB;AAK1B,IAAM,yCAAyC;AAC/C,IAAM,yCAAyC;AAC/C,IAAM,wCAAwC;AAC9C,IAAM,wCAAwC;AAC9C,IAAM,uCAAuC,MAAM;AACnD,IAAM,eAA+B,CAAC;AACtC,IAAM,UAAU,IAAI,YAAY;AAIzB,IAAM,kCAAkC,KAAK,OAAO;AACpD,IAAM,kCAAkC;AACxC,IAAM,0CAA0C,OAAO;AACvD,IAAM,0CAA0C;AAQvD,IAAM,qBAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AACb;AAOO,SAAS,iBACd,WACA,UAAmC,CAAC,GACZ;AACxB,QAAM,EAAE,QAAQ,aAAa,iBAAiB,IAAI,mBAAmB,OAAO;AAC5E,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,WAAW,oBAAoB;AACrC,QAAM,gBAAgB,WAAW;AACjC,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,aAAa,WAAW,UAAU,UAAU;AAClD,QAAM,YAAY,GAAG,WAAW,KAAS,aAAa,EAAE,KAAS,KAAK,KAAS,aAAa,SAAS,UAAU;AAI/G,QAAM,wBAAwB,OAAO,EAAE,QAAQ,WAAW,QAAQ,CAAC;AACnE,MACE,sBAAsB,QAAQ,WAAW,UACzC,sBAAsB,QAAQ,cAAc,aAC5C,sBAAsB,QAAQ,YAAY,SAC1C;AACA,0BAAsB,UAAU,EAAE,QAAQ,WAAW,QAAQ;AAAA,EAC/D;AACA,QAAM,qBAAqB,sBAAsB;AACjD,QAAM,iBAAiB;AAAA,IACrB,MAAM,sBAAsB,YAAY;AAAA,IACxC,CAAC,kBAAkB;AAAA,EACrB;AAEA,QAAM,CAAC,aAAa,cAAc,IAAI,SAAoC,kBAAkB;AAE5F,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAKtC,IAAI;AACd,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAuC,MAAM;AAC3F,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AACrD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAuB,IAAI;AAC/D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,yBAAyB,0BAA0B,IAAI;AAAA,IAC5D;AAAA,EACF;AACA,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,IAAI;AACzD,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,SAAS,KAAK;AACpE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AACxD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AACxD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AACxD,QAAM,mBAAmB,OAAO,KAAK;AACrC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,CAAC;AAEhD,QAAM,CAAC,UAAU,WAAW,IAAI,SAA6B,MAAM;AACnE,QAAM,kBAAkB,OAAO,KAAK;AACpC,QAAM,0BAA0B,OAAO,KAAK;AAC5C,QAAM,oBAAoB,OAAsB,IAAI;AACpD,QAAM,oBAAoB,OAAsB,IAAI;AACpD,QAAM,cAAc,OAAO,KAAK;AAChC,QAAM,cAAc,OAAO,KAAK;AAChC,QAAM,kBAAkB,OAAO,KAAK;AACpC,QAAM,kBAAkB,OAAO,KAAK;AACpC,QAAM,mBAAmB,OAAO,KAAK;AACrC,QAAM,mBAAmB,OAAO,KAAK;AACrC,QAAM,cAAc,OAA2B,MAAM;AACrD,QAAM,yBAAyB,OAAO,KAAK;AAC3C,QAAM,8BAA8B,OAAO,KAAK;AAChD,QAAM,iBAAiB,OAA+B,IAAI;AAC1D,QAAM,eAAe,OAAsB,IAAI;AAC/C,QAAM,gBAAgB,OAAO,CAAC;AAC9B,QAAM,0BAA0B,OAAO,CAAC;AACxC,QAAM,iBAAiB,OAAkC,kBAAkB;AAC3E,QAAM,mBAAmB,OAGtB;AAAA,IACD,UAAU;AAAA,IACV,QAAQ;AAAA,EACV,CAAC;AAGD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,SAAS;AAI9D,YAAU,MAAM;AACd,4BAAwB,WAAW;AACnC,kBAAc,IAAI;AAClB,oBAAgB,UAAU;AAC1B,oBAAgB,UAAU;AAC1B,qBAAiB,UAAU;AAC3B,qBAAiB,UAAU;AAC3B,wBAAoB,IAAI;AACxB,qBAAiB,KAAK;AACtB,oBAAgB,KAAK;AACrB,oBAAgB,KAAK;AACrB,qBAAiB,KAAK;AACtB,WAAO,MAAM;AACX,8BAAwB,WAAW;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,WAAW,OAAO,SAAS,UAAU,CAAC;AAE/D,YAAU,MAAM;AAGd,QAAI,aAAa,YAAY,WAAW;AACtC,mBAAa,UAAU;AACvB,wBAAkB,SAAS;AAC3B,qBAAe,UAAU;AACzB,qBAAe,kBAAkB;AACjC,eAAS,IAAI;AACb,kBAAY,KAAK;AACjB,kBAAY,KAAK;AACjB,uBAAiB,UAAU,EAAE,UAAU,OAAO,QAAQ,KAAK;AAC3D,iCAA2B,IAAI;AAC/B,sBAAgB,KAAK;AACrB,sBAAgB,KAAK;AACrB,uBAAiB,KAAK;AACtB,uBAAiB,KAAK;AACtB,wBAAkB,IAAI;AACtB,6BAAuB,KAAK;AAC5B,sBAAgB,UAAU;AAC1B,8BAAwB,UAAU;AAClC,wBAAkB,UAAU;AAC5B,wBAAkB,UAAU;AAC5B,kBAAY,UAAU;AACtB,kBAAY,UAAU;AACtB,sBAAgB,UAAU;AAC1B,sBAAgB,UAAU;AAC1B,uBAAiB,UAAU;AAC3B,uBAAiB,UAAU;AAC3B,kBAAY,UAAU;AACtB,kBAAY,MAAM;AAClB,6BAAuB,UAAU;AACjC,kCAA4B,UAAU;AAAA,IACxC;AAIA,UAAM,aAAa,cAAc,UAAU;AAC3C,kBAAc,UAAU;AACxB,QAAI,CAAC,aAAa,CAAC,eAAe;AAOhC,UACE,aACA,WACA,CAAC,YACD,CAAC,cACD,YAAY,YAAY,UACxB,uBAAuB,SACvB;AACA,oCAA4B,UAAU;AAAA,MACxC;AACA,yBAAmB,MAAM;AACzB;AAAA,IACF;AAGA,QAAI,aAAa,WAAW;AAC1B,kCAA4B,UAAU;AACtC,yBAAmB,MAAM;AACzB,wBAAkB,KAAK;AACvB;AAAA,IACF;AACA,UAAM,4BAA4B,4BAA4B,WAAW,CAAC;AAC1E,gCAA4B,UAAU;AACtC,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,MAChB,cAAc,YAAY,cAC1B,CAAC,WAAW,OAAO,WACnB,sBAAsB,QAAQ,WAAW,UACzC,sBAAsB,QAAQ,cAAc,aAC5C,sBAAsB,QAAQ,YAAY;AAC5C,mBAAe,UAAU;AAOzB,QAAI,UAA0B,CAAC;AAC/B,QAAI,eAAe;AACnB,QAAI,aAAmD;AACvD,UAAM,QAAQ,MAAM;AAKlB,UAAI,eAAe,MAAM;AACvB,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AACA,UAAI,CAAC,UAAU,GAAG;AAChB,kBAAU,CAAC;AACX,uBAAe;AACf;AAAA,MACF;AACA,UAAI,QAAQ,WAAW,GAAG;AACxB;AAAA,MACF;AACA,YAAM,QAAQ;AACd,gBAAU,CAAC;AACX,qBAAe;AAIf,YAAM,cAAc,MAAM,MAAM,SAAS,CAAC;AAC1C,UAAI,aAAa;AACf,cAAM,sBAAsB,KAAK,IAAI,GAAG,MAAM,IAAI,mBAAmB,CAAC;AACtE,wBAAgB,UAAU,KAAK,IAAI,gBAAgB,SAAS,mBAAmB;AAC/E,gCAAwB,UAAU,KAAK;AAAA,UACrC,wBAAwB;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AACA,YAAM,SAAS,qBAAqB,OAAO,gBAAgB;AAC3D,UAAI,WAAW,QAAW;AACxB,mCAA2B,MAAM;AAAA,MACnC;AACA,YAAM,UAAU,eAAe;AAC/B,YAAM,OAAO,gCAAgC,SAAS,KAAK;AAC3D,YAAM,WAAW;AAAA,QACf,GAAG;AAAA,QACH,WAAW,QAAQ,aAAa,KAAK;AAAA,MACvC;AACA,qBAAe,UAAU;AACzB,qBAAe,QAAQ;AACvB,wBAAkB,UAAU,SAAS,OAAO,CAAC,GAAG,YAAY;AAC5D,wBAAkB,UAAU,wBAAwB,SAAS,MAAM;AACnE,UAAI,SAAS,WAAW;AACtB,oBAAY,UAAU;AACtB,oBAAY,IAAI;AAAA,MAClB;AAAA,IACF;AACA,UAAM,gBAAgB,MAAM;AAC1B,UAAI,CAAC,UAAU,EAAG;AAClB,qBAAe,WAAW,OAAO,EAAE;AAAA,IACrC;AAEA,UAAM,YAAY;AAChB,UAAI;AACF,YAAI,2BAA2B;AAC7B,6BAAmB,YAAY;AAC/B,gBAAM,SAAS,wBAAwB;AACvC,cAAI,OAA8B,EAAE,MAAM,SAAS;AACnD,cAAI;AACF,mBAAO,MAAM,sBAAsB,QAAQ,aAAa,WAAW,QAAQ;AAAA,cACzE,QAAQ,WAAW;AAAA,YACrB,CAAC;AAAA,UACH,QAAQ;AACN,gBAAI,WAAW,OAAO,QAAS;AAI/B,mBAAO,EAAE,MAAM,SAAS;AAAA,UAC1B;AACA,cAAI,CAAC,UAAU,EAAG;AAClB,cAAI,KAAK,SAAS,UAAU;AAC1B,kBAAM,UAAU,eAAe;AAC/B,8BAAkB,QAAQ,QAAQ,KAAK,MAAM;AAC7C,kBAAM,SAAS,qBAAqB,KAAK,QAAQ,gBAAgB;AACjE,kBAAM,OAAO,gCAAgC,SAAS,KAAK,MAAM;AACjE,kBAAM,WAAW;AAAA,cACf,GAAG;AAAA,cACH,WAAW,QAAQ,aAAa,KAAK;AAAA,YACvC;AACA,2BAAe,UAAU;AACzB,8BAAkB,UAAU,SAAS,OAAO,CAAC,GAAG,YAAY;AAC5D,8BAAkB,UAAU,wBAAwB,SAAS,MAAM;AACnE,4BAAgB,UAAU,KAAK,IAAI,gBAAgB,SAAS,KAAK,cAAc;AAC/E,oCAAwB,UAAU,KAAK;AAAA,cACrC,wBAAwB;AAAA,cACxB,KAAK;AAAA,YACP;AACA,gBAAI,WAAW,QAAW;AACxB,yCAA2B,MAAM;AAAA,YACnC;AACA,2BAAe,QAAQ;AACvB,gBAAI,SAAS,WAAW;AACtB,0BAAY,UAAU;AACtB,0BAAY,IAAI;AAAA,YAClB;AAAA,UACF,WAAW,KAAK,SAAS,UAAU;AAKjC,mCAAuB,UAAU;AACjC,qBAAS,IAAI;AAAA,UACf;AAAA,QACF;AACA,YAAI,CAAC,cAAc,CAAC,uBAAuB,SAAS;AAClD,6BAAmB,YAAY;AAI/B,gBAAM,SAAS,MAAM,gBAAgB,QAAQ,aAAa,WAAW;AAAA,YACnE,QAAQ,OAAO;AAAA,YACf,UAAU;AAAA,YACV,cAAc,OAAO;AAAA,YACrB,YAAY;AAAA,YACZ,iBAAiB;AAAA,YACjB,QAAQ,WAAW;AAAA,UACrB,CAAC;AACD,cAAI,CAAC,UAAU,GAAG;AAChB;AAAA,UACF;AACA,gBAAM,SAAS,qBAAqB,OAAO,QAAQ,gBAAgB;AACnE,gBAAM,WAAW,+BAA+B,OAAO,MAAM;AAI7D,kCAAwB,WAAW;AACnC,0BAAgB,UAAU;AAC1B,0BAAgB,UAAU;AAC1B,2BAAiB,UAAU;AAC3B,0BAAgB,KAAK;AACrB,0BAAgB,KAAK;AACrB,2BAAiB,KAAK;AACtB,yBAAe,UAAU;AACzB,4BAAkB,UAAU,SAAS,OAAO,CAAC,GAAG,YAAY,OAAO;AACnE,4BAAkB,UAChB,wBAAwB,SAAS,MAAM,KAAK,OAAO;AACrD,sBAAY,UAAU,OAAO,YAAY,SAAS;AAClD,sBAAY,UAAU;AACtB,0BAAgB,UAAU,OAAO;AACjC,kCAAwB,UAAU,OAAO;AACzC,iCAAuB,UAAU;AACjC,iCAAuB,IAAI;AAC3B,mBAAS,IAAI;AACb,cAAI,WAAW,QAAW;AACxB,uCAA2B,MAAM;AAAA,UACnC;AACA,yBAAe,QAAQ;AACvB,sBAAY,OAAO,YAAY,SAAS,SAAS;AACjD,sBAAY,KAAK;AACjB,4BAAkB,KAAK;AAAA,QACzB;AACA,YAAI,YAAY;AACd,4BAAkB,KAAK;AAAA,QACzB;AACA,cAAM,SAAS,OAAO,aAAa,aAAa,WAAW;AAAA,UACzD,OAAO,wBAAwB;AAAA,UAC/B,QAAQ,WAAW;AAAA,UACnB,QAAQ,MAAM;AAIZ,iBAAK,QAAQ,QAAQ,EAClB,KAAK,MAAM,iBAAiB,SAAS,CAAC,EACtC,MAAM,CAAC,UAAU;AAChB,kBAAI,UAAU,GAAG;AACf,yBAAS,eAAe,KAAK,CAAC;AAAA,cAChC;AAAA,YACF,CAAC;AAAA,UACL;AAAA,UACA,eAAe,CAAC,UAAU;AACxB,gBAAI,UAAU,GAAG;AACf,iCAAmB,KAAK;AAAA,YAC1B;AAAA,UACF;AAAA,QACF,CAAC;AACD,yBAAiB,SAAS,QAAQ;AAChC,cAAI,CAAC,UAAU,EAAG;AAClB,gBAAM,eAAe;AACrB,gBAAM,oBAAoB,iBAAiB,YAAY;AACvD,gBAAM,iBAAiB,QAAQ,WAAW,IAAI,IAAI;AAClD,cACE,QAAQ,SAAS,MAChB,QAAQ,UAAU,2CACjB,eAAe,iBAAiB,oBAC9B,0CACJ;AACA,kBAAM;AAAA,UACR;AACA,kBAAQ,KAAK,YAAY;AACzB,2BAAiB,QAAQ,WAAW,IAAI,IAAI,KAAK;AACjD,cACE,QAAQ,UAAU,2CAClB,gBAAgB,yCAChB;AACA,kBAAM;AAAA,UACR,OAAO;AACL,0BAAc;AAAA,UAChB;AAAA,QACF;AACA,YAAI,UAAU,GAAG;AACf,gBAAM;AACN,6BAAmB,OAAO;AAAA,QAC5B;AAAA,MACF,SAAS,OAAO;AACd,YAAI,UAAU,GAAG;AACf,gBAAM;AACN,mBAAS,eAAe,KAAK,CAAC;AAC9B,6BAAmB,OAAO;AAI1B,4BAAkB,KAAK;AAAA,QACzB;AAAA,MACF;AAAA,IACF,GAAG;AAEH,WAAO,MAAM;AACX,iBAAW,MAAM;AACjB,UAAI,cAAc,YAAY,YAAY;AACxC,sBAAc,UAAU,aAAa;AAAA,MACvC;AACA,UAAI,eAAe,YAAY,YAAY;AACzC,uBAAe,UAAU;AAAA,MAC3B;AACA,UAAI,eAAe,MAAM;AACvB,qBAAa,UAAU;AAAA,MACzB;AAAA,IACF;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,iBAAiB,MACrB,iBAAiB,WACjB,gBAAgB,WAChB,gBAAgB,WAChB,iBAAiB,WACjB,iBAAiB;AAEnB,QAAM,YAAY;AAAA,IAChB,MACE,8BAA8B,OAAO,eAAe,cAAc,sBAAsB;AACtF,UAAI,CAAC,eAAe,KAAK,CAAC,aAAa,eAAe,KAAK,CAAC,YAAY,SAAS;AAC/E,eAAO;AAAA,MACT;AACA,YAAM,SAAS,kBAAkB;AACjC,UAAI,WAAW,MAAM;AACnB,0BAAkB,UAAU;AAC5B,oBAAY,UAAU;AACtB,oBAAY,KAAK;AACjB,eAAO;AAAA,MACT;AACA,YAAM,aAAa,wBAAwB;AAC3C,YAAM,YAAY,MAAM,eAAe,KAAK,wBAAwB,YAAY;AAChF,sBAAgB,UAAU;AAC1B,sBAAgB,IAAI;AACpB,UAAI,YAAY;AAChB,UAAI;AACF,cAAM,SAAS,MAAM,gBAAgB,QAAQ,aAAa,WAAW;AAAA,UACnE;AAAA,UACA,UAAU;AAAA,UACV,cAAc;AAAA,UACd,YAAY;AAAA,UACZ;AAAA,QACF,CAAC;AACD,YAAI,CAAC,UAAU,GAAG;AAChB,iBAAO;AAAA,QACT;AACA,YAAI,OAAO,OAAO,WAAW,GAAG;AAC9B,4BAAkB,UAAU;AAC5B,sBAAY,UAAU;AACtB,sBAAY,KAAK;AACjB,iBAAO;AAAA,QACT;AACA,cAAM,UAAU,eAAe;AAC/B,2BAAmB,QAAQ,QAAQ,OAAO,MAAM;AAIhD,cAAM,OAAO,+BAA+B,CAAC,GAAG,OAAO,QAAQ,GAAG,QAAQ,MAAM,GAAG;AAAA,UACjF,WAAW;AAAA,QACb,CAAC;AACD,YAAI,gBAAgB,kBAAkB,KAAK,MAAM,IAAI,kBAAkB,QAAQ,MAAM,GAAG;AAGtF,4BAAkB;AAClB,iBAAO;AAAA,QACT;AACA,uBAAe,SAAS,MAAM;AAC9B,cAAM,SAAS,qBAAqB,OAAO,QAAQ,gBAAgB;AACnE,cAAM,WAAW;AAAA,UACf,GAAG;AAAA,UACH,WAAW,QAAQ,aAAa,KAAK;AAAA,QACvC;AACA,cAAM,iBAAiB,SAAS,OAAO,CAAC,GAAG,YAAY;AACvD,YAAI,mBAAmB,QAAQ,kBAAkB,QAAQ;AACvD,gBAAM,IAAI,MAAM,8DAA8D;AAAA,QAChF;AACA,cAAM,iBAAiB,wBAAwB,SAAS,MAAM;AAC9D,cAAM,iBAAiB,wBAAwB,QAAQ,MAAM;AAC7D,uBAAe,UAAU;AACzB,sBAAc;AACd,0BAAkB,UAAU;AAC5B,0BAAkB,UAAU;AAC5B,gCAAwB,UAAU,kBAAkB,SAAS,MAAM;AAInE,cAAM,sBAAsB,OAAO;AACnC,oBAAY,UAAU;AACtB,cAAM,kBACJ,mBAAmB,QAAQ,mBAAmB,QAAQ,iBAAiB;AACzE,YAAI,QAAwB;AAC5B,YAAI,eAAe;AACnB,YAAI,gBAAgB;AACpB,YAAI,YAAY,YAAY,aAAa,iBAAiB;AACxD,gBAAM,YAAY,gBAAgB;AAClC,kBAAQ,mBAAmB,SAAS,iBAAiB,aAAa,SAAS;AAC3E,sBAAY,UAAU;AACtB,cAAI,iBAAiB;AAKnB,wBAAY,UAAU;AACtB,2BAAe;AAAA,UACjB;AAAA,QACF,OAAO;AAGL,0BAAgB;AAAA,QAClB;AACA,wBAAgB,UAAU;AAC1B,wBAAgB,MAAM;AACpB,cAAI,WAAW,QAAW;AACxB,uCAA2B,MAAM;AAAA,UACnC;AACA,yBAAe,QAAQ;AACvB,sBAAY,mBAAmB;AAC/B,cAAI,UAAU,MAAM;AAClB,wBAAY,KAAK;AAAA,UACnB;AACA,cAAI,cAAc;AAChB,wBAAY,SAAS;AAAA,UACvB,WAAW,eAAe;AACxB,2BAAe,CAAC,UAAU,QAAQ,CAAC;AAAA,UACrC;AACA,0BAAgB,KAAK;AAAA,QACvB,CAAC;AACD,oBAAY;AACZ,eAAO;AAAA,MACT,SAAS,QAAQ;AACf,YAAI,CAAC,UAAU,EAAG,QAAO;AACzB,cAAM;AAAA,MACR,UAAE;AACA,YAAI,CAAC,aAAa,UAAU,GAAG;AAC7B,0BAAgB,UAAU;AAC1B,0BAAgB,KAAK;AAAA,QACvB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,IACH,CAAC,QAAQ,aAAa,WAAW,cAAc;AAAA,EACjD;AAEA,QAAM,aAAa,YAAY,YAA8B;AAC3D,QAAI,CAAC,eAAe,KAAK,CAAC,aAAa,eAAe,KAAK,CAAC,YAAY,SAAS;AAC/E,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,EAAE,wBAAwB;AAC7C,UAAM,YAAY,MAAM,eAAe,KAAK,wBAAwB,YAAY;AAChF,wBAAoB,IAAI;AACxB,qBAAiB,UAAU;AAC3B,qBAAiB,IAAI;AACrB,QAAI,YAAY;AAChB,QAAI;AACF,YAAM,SAAS,MAAM,uBAAuB,QAAQ,aAAa,WAAW;AAAA,QAC1E,OAAO;AAAA,QACP,UAAU;AAAA,QACV,cAAc;AAAA,QACd,YAAY;AAAA,QACZ;AAAA,MACF,CAAC;AACD,UAAI,CAAC,UAAU,GAAG;AAChB,eAAO;AAAA,MACT;AACA,UAAI,OAAO,OAAO,WAAW,GAAG;AAC9B,oBAAY,UAAU;AACtB,oBAAY,KAAK;AACjB,eAAO;AAAA,MACT;AACA,qBAAe,SAAS,MAAM;AAC9B,YAAM,SAAS,qBAAqB,OAAO,QAAQ,gBAAgB;AAEnE,YAAM,WAAW,+BAA+B,OAAO,QAAQ,EAAE,WAAW,SAAS,CAAC;AACtF,YAAM,iBAAiB,SAAS,OAAO,CAAC,GAAG,YAAY;AACvD,YAAM,iBAAiB,wBAAwB,SAAS,MAAM;AAC9D,qBAAe,UAAU;AACzB,wBAAkB,UAAU;AAC5B,wBAAkB,UAAU;AAC5B,kBAAY,UAAU;AACtB,YAAM,YAAY,KAAK,IAAI,gBAAgB,SAAS,kBAAkB,CAAC;AACvE,sBAAgB,UAAU;AAC1B,YAAM,QACJ,OAAO,YACP,SAAS,aACR,mBAAmB,QAAQ,iBAAiB;AAC/C,kBAAY,UAAU;AACtB,6BAAuB,UAAU;AACjC,6BAAuB,IAAI;AAC3B,eAAS,IAAI;AACb,kBAAY,UAAU;AACtB,uBAAiB,UAAU;AAC3B,oBAAc,IAAI;AAClB,sBAAgB,MAAM;AACpB,YAAI,WAAW,QAAW;AACxB,qCAA2B,MAAM;AAAA,QACnC;AACA,uBAAe,QAAQ;AACvB,oBAAY,KAAK;AACjB,oBAAY,KAAK;AACjB,oBAAY,SAAS;AACrB,yBAAiB,KAAK;AAAA,MACxB,CAAC;AACD,kBAAY;AACZ,aAAO;AAAA,IACT,SAAS,QAAQ;AACf,UAAI,CAAC,UAAU,EAAG,QAAO;AACzB,YAAM;AAAA,IACR,UAAE;AACA,UAAI,CAAC,aAAa,UAAU,GAAG;AAC7B,yBAAiB,UAAU;AAC3B,yBAAiB,KAAK;AAAA,MACxB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,WAAW,cAAc,CAAC;AAEnD,QAAM,YAAY,YAAY,YAA8B;AAC1D,QAAI,CAAC,eAAe,KAAK,CAAC,aAAa,eAAe,KAAK,CAAC,YAAY,SAAS;AAC/E,aAAO;AAAA,IACT;AACA,UAAM,gBAAgB,kBAAkB;AACxC,QAAI,kBAAkB,MAAM;AAC1B,kBAAY,UAAU;AACtB,kBAAY,KAAK;AACjB,aAAO;AAAA,IACT;AACA,UAAM,aAAa,wBAAwB;AAC3C,UAAM,YAAY,MAAM,eAAe,KAAK,wBAAwB,YAAY;AAChF,oBAAgB,UAAU;AAC1B,oBAAgB,IAAI;AACpB,QAAI,YAAY;AAChB,QAAI;AACF,YAAM,SAAS,MAAM,uBAAuB,QAAQ,aAAa,WAAW;AAAA,QAC1E,OAAO;AAAA,QACP,UAAU;AAAA,QACV,cAAc;AAAA,QACd,YAAY;AAAA,QACZ;AAAA,MACF,CAAC;AACD,UAAI,CAAC,UAAU,GAAG;AAChB,eAAO;AAAA,MACT;AACA,UAAI,OAAO,OAAO,WAAW,GAAG;AAC9B,sBAAc,IAAI;AAClB,oBAAY,UAAU;AACtB,oBAAY,KAAK;AAEjB,gCAAwB,UAAU;AAClC,oBAAY,UAAU;AACtB,oBAAY,MAAM;AAClB,uBAAe,CAAC,UAAU,QAAQ,CAAC;AACnC,eAAO;AAAA,MACT;AACA,YAAM,UAAU,eAAe;AAC/B,wBAAkB,QAAQ,QAAQ,OAAO,MAAM;AAC/C,YAAM,SAAS,qBAAqB,OAAO,QAAQ,gBAAgB;AACnE,YAAM,iBAAiB,QAAQ,OAAO,CAAC,GAAG,YAAY;AAEtD,YAAM,OAAO,gCAAgC,SAAS,OAAO,MAAM;AACnE,YAAM,WAAW;AAAA,QACf,GAAG;AAAA,QACH,WAAW,QAAQ,aAAa,KAAK,aAAa,OAAO;AAAA,MAC3D;AACA,YAAM,iBAAiB,SAAS,OAAO,CAAC,GAAG,YAAY;AACvD,YAAM,iBAAiB,wBAAwB,SAAS,MAAM;AAC9D,UAAI,mBAAmB,QAAQ,kBAAkB,eAAe;AAC9D,cAAM,IAAI,MAAM,8DAA8D;AAAA,MAChF;AACA,qBAAe,UAAU;AACzB,wBAAkB,UAAU;AAC5B,wBAAkB,UAAU;AAE5B,UACE,mBAAmB,SAClB,mBAAmB,QAClB,iBAAiB,kBAChB,SAAS,aACR,SAAS,OAAO,CAAC,GAAG,SAAS,qBAC7B,iBAAiB,IACrB;AACA,oBAAY,UAAU;AAAA,MACxB;AACA,YAAM,eAAe,YAAY;AACjC,YAAM,YAAY,KAAK,IAAI,gBAAgB,SAAS,cAAc;AAClE,sBAAgB,UAAU;AAC1B,YAAM,QAAQ,OAAO,YAAY,iBAAiB;AAClD,kBAAY,UAAU;AACtB,UAAI,aAAa;AACjB,UAAI,CAAC,OAAO;AACV,gCAAwB,UAAU;AAClC,oBAAY,UAAU;AACtB,qBAAa;AAAA,MACf;AACA,sBAAgB,UAAU;AAC1B,oBAAc,IAAI;AAClB,sBAAgB,MAAM;AACpB,YAAI,WAAW,QAAW;AACxB,qCAA2B,MAAM;AAAA,QACnC;AACA,uBAAe,QAAQ;AACvB,oBAAY,YAAY;AACxB,oBAAY,KAAK;AACjB,YAAI,YAAY;AACd,sBAAY,MAAM;AAClB,yBAAe,CAAC,UAAU,QAAQ,CAAC;AAAA,QACrC;AACA,wBAAgB,KAAK;AAAA,MACvB,CAAC;AACD,kBAAY;AACZ,aAAO;AAAA,IACT,SAAS,QAAQ;AAGf,UAAI,CAAC,UAAU,GAAG;AAChB,eAAO;AAAA,MACT;AACA,oBAAc,eAAe,MAAM,CAAC;AAGpC,YAAM;AAAA,IACR,UAAE;AACA,UAAI,CAAC,aAAa,UAAU,GAAG;AAC7B,wBAAgB,UAAU;AAC1B,wBAAgB,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,WAAW,cAAc,CAAC;AAEnD,QAAM,iBAAiB;AAAA,IACrB,OAAO,UAAkB,sBAAmE;AAC1F,YAAM,SAAS,mBAAmB;AAClC,UAAI,CAAC,eAAe,KAAK,CAAC,aAAa,CAAC,OAAO,cAAc,QAAQ,KAAK,WAAW;AACnF,eAAO;AAGT,UAAI,QAAQ,QAAS,QAAO;AAE5B,YAAM,aAAa,EAAE,wBAAwB;AAC7C,0BAAoB,IAAI;AACxB,YAAM,UAAU,MAAM,eAAe,wBAAwB,WAAW,eAAe;AACvF,YAAM,eAAe,YAAY;AACjC,qBAAe,SAAS,MAAM;AAC9B,oBAAc,WAAW;AACzB,kBAAY,UAAU;AACtB,kBAAY,SAAS;AACrB,sBAAgB,UAAU,gBAAgB,UAAU,iBAAiB,UAAU;AAC/E,sBAAgB,KAAK;AACrB,sBAAgB,KAAK;AACrB,uBAAiB,KAAK;AACtB,uBAAiB,UAAU;AAC3B,uBAAiB,IAAI;AACrB,UAAI,YAAY;AAChB,UAAI;AACF,cAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,UAC5C,iBAAiB,QAAQ,aAAa,WAAW,WAAW,GAAG,EAAE,UAAU,IAAI,CAAC;AAAA,UAChF,aAAa,QAAQ,aAAa,WAAW,UAAU,EAAE,UAAU,IAAI,CAAC;AAAA,QAC1E,CAAC;AAID,YAAI,QAAQ,QAAS,QAAO;AAC5B,YAAI,CAAC,QAAQ,EAAG,QAAO;AACvB,YAAI,CAAC,OAAO,KAAK,CAAC,UAAU,MAAM,aAAa,QAAQ,EAAG,QAAO;AAGjE,cAAM,SAAS,+BAA+B,QAAQ;AAAA,UACpD,WAAW;AAAA,UACX,UAAU,kCAAkC;AAAA,QAC9C,CAAC;AACD,cAAM,WAAW,+BAA+B,CAAC,GAAG,OAAO,QAAQ,GAAG,SAAS,GAAG;AAAA,UAChF,WAAW;AAAA,QACb,CAAC;AACD,YAAI,CAAC,SAAS,OAAO,KAAK,CAAC,UAAU,MAAM,aAAa,QAAQ,EAAG,QAAO;AAC1E,uBAAe,SAAS,MAAM;AAC9B,sBAAc,WAAW;AACzB,cAAM,SAAS,qBAAqB,SAAS,QAAQ,gBAAgB;AACrE,uBAAe,UAAU;AACzB,0BAAkB,UAAU,SAAS,OAAO,CAAC,EAAG;AAChD,0BAAkB,UAAU,wBAAwB,SAAS,MAAM;AACnE,wBAAgB,UAAU,KAAK,IAAI,gBAAgB,SAAS,kBAAkB,WAAW,CAAC;AAC1F,oBAAY,UAAU,CAAC,WAAW,SAAS,OAAO,CAAC,CAAE;AAGrD,oBAAY,UACV,UAAU,SAAS,KACnB,SAAS,cACR,kBAAkB,WAAW,KAAK,gBAAgB;AACrD,+BAAuB,UAAU;AACjC,+BAAuB,IAAI;AAC3B,iBAAS,IAAI;AACb,oBAAY,UAAU;AACtB,uBAAe,QAAQ;AACvB,oBAAY,YAAY,OAAO;AAC/B,oBAAY,YAAY,OAAO;AAC/B,0BAAkB,KAAK;AACvB,oBAAY,SAAS;AACrB,sBAAc,IAAI;AAClB,YAAI,WAAW,OAAW,4BAA2B,MAAM;AAC3D,oBAAY;AACZ,eAAO;AAAA,MACT,SAAS,QAAQ;AACf,YAAI,CAAC,QAAQ,KAAK,QAAQ,QAAS,QAAO;AAC1C,cAAM;AAAA,MACR,UAAE;AACA,YAAI,QAAQ,GAAG;AACb,2BAAiB,UAAU;AAC3B,2BAAiB,KAAK;AACtB,cAAI,CAAC,aAAa,iBAAiB,QAAQ;AACzC,wBAAY,UAAU;AACtB,wBAAY,MAAM;AAClB,2BAAe,CAAC,UAAU,QAAQ,CAAC;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,cAAc;AAAA,EACjD;AAEA,QAAM,uBAAuB;AAAA,IAC3B,OAAO,oBAAoE;AACzE,UAAI,CAAC,aAAa,CAAC,eAAe,EAAG,QAAO;AAC5C,UAAI,aAAa,wBAAwB;AACzC,YAAM,UAAU,MAAM,eAAe,KAAK,eAAe,wBAAwB;AACjF,UAAI;AAGF,cAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,+BAAmB;AAClE,YAAI,CAAC,QAAQ,EAAG,QAAO;AACvB,cAAM,cAAc,MAAM,sBAAsB;AAAA,UAC9C;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,gBAAgB;AAAA,UAChB,SAAS;AAAA,QACX,CAAC;AACD,YAAI,CAAC,eAAe,CAAC,QAAQ,EAAG,QAAO;AACvC,YAAI,CAAC,eAAe,QAAQ,OAAO,KAAK,CAAC,UAAU,MAAM,aAAa,YAAY,MAAM,GAAG;AACzF,gBAAM,aAAa,eAAe,YAAY,MAAM;AACpD,uBAAa,wBAAwB;AACrC,cAAI,CAAE,MAAM,cAAe,CAAC,QAAQ,EAAG,QAAO;AAAA,QAChD;AACA,4BAAoB;AAAA,UAClB;AAAA,UACA;AAAA,UACA,QAAQ,YAAY;AAAA,UACpB,QAAQ,YAAY;AAAA,QACtB,CAAC;AACD,eAAO,YAAY;AAAA,MACrB,SAAS,QAAQ;AACf,YAAI,CAAC,QAAQ,EAAG,QAAO;AACvB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,WAAW,gBAAgB,cAAc;AAAA,EAC5E;AAEA,QAAM,eAAe,YAAY,YAA2B;AAG1D,QAAI,CAAC,eAAe,EAAG;AACvB,QAAI,iBAAiB,SAAS;AAC5B,8BAAwB,WAAW;AACnC,uBAAiB,UAAU;AAC3B,uBAAiB,KAAK;AAAA,IACxB;AACA,QAAI,CAAC,aAAa,eAAe,GAAG;AAClC;AAAA,IACF;AACA,4BAAwB,WAAW;AACnC,wBAAoB,IAAI;AACxB,qBAAiB,UAAU;AAC3B,qBAAiB,IAAI;AACrB,kBAAc,IAAI;AAClB,aAAS,IAAI;AACb,QAAI,YAAY;AAChB,QAAI;AACF,qBAAe,SAAS,MAAM;AAC9B,kBAAY,UAAU;AACtB,kBAAY,UAAU;AACtB,wBAAkB,UAAU;AAC5B,wBAAkB,UAAU;AAC5B,qBAAe,UAAU;AACzB,6BAAuB,UAAU;AACjC,8BAAwB,UAAU;AAClC,kBAAY,UAAU;AACtB,uBAAiB,UAAU;AAC3B,sBAAgB,MAAM;AACpB,oBAAY,KAAK;AACjB,oBAAY,KAAK;AACjB,uBAAe,kBAAkB;AACjC,0BAAkB,IAAI;AACtB,oBAAY,MAAM;AAClB,uBAAe,CAAC,UAAU,QAAQ,CAAC;AACnC,yBAAiB,KAAK;AAAA,MACxB,CAAC;AACD,kBAAY;AAEZ,YAAM,QAAQ,QAAQ;AAAA,IACxB,UAAE;AACA,UAAI,CAAC,WAAW;AACd,yBAAiB,UAAU;AAC3B,yBAAiB,KAAK;AAAA,MACxB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,WAAW,cAAc,CAAC;AAErC,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,gBAAgB,kBAAkB,YAAY,SAAS;AAC7D,QAAM,WAAW,QAAQ,MAAM;AAC7B,UAAM,UACJ,kBAAkB,WAAW,UAC7B,iBAAiB,cAAc,aAC/B,cAAc,KAAK,CAAC,UAAU,MAAM,aAAa,iBAAiB,MAAM,IACpE,iBAAiB,SACjB;AACN,UAAM,kBAAkB,EAAE,cAAc,YAAY,YAAY,aAAa,QAAQ,EAAE;AACvF,QAAI,QAAQ,WAAW,EAAG,QAAO,cAAc,eAAe,eAAe;AAC7E,UAAM,MAAM,IAAI,IAAI,cAAc,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AAC1D,WAAO;AAAA,MACL,CAAC,GAAG,eAAe,GAAG,QAAQ,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC;AAAA,MACnE;AAAA,IACF;AAAA,EACF,GAAG,CAAC,eAAe,UAAU,YAAY,WAAW,OAAO,kBAAkB,QAAQ,SAAS,CAAC;AAE/F,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,eAAe,kBAAkB,0BAA0B;AAAA,IAC3D,uBAAuB,kBAAkB,iBAAiB,QAAQ,WAAW;AAAA,IAC7E,iBAAiB,kBAAkB,kBAAkB;AAAA,IACrD,cAAc,kBAAkB,gBAAgB,UAAU;AAAA,IAC1D,aAAa,kBAAkB,YAAY,QAAQ;AAAA,IACnD,iBAAiB,kBAAkB,YAAY,YAAY;AAAA,IAC3D,gBAAgB,aAAa,QAAQ,kBAAkB,iBAAiB;AAAA,IACxE,qBAAqB,mBAAmB;AAAA,IACxC,UAAU,CAAC,kBAAkB,QAAQ;AAAA,IACrC,cAAc,CAAC,kBAAkB,QAAQ;AAAA,IACzC;AAAA,IACA,UAAU,CAAC,kBAAkB,QAAQ;AAAA,IACrC,cAAc,CAAC,kBAAkB,QAAQ;AAAA,IACzC;AAAA,IACA,eAAe,CAAC,kBAAkB,QAAQ;AAAA,IAC1C;AAAA,IACA,eAAe,CAAC,kBAAkB,QAAQ;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,mBAAmB;AAAA,IAClC,OAAO,kBAAmB,cAAc,QAAS;AAAA,EACnD;AACF;AAYO,SAAS,+BACd,QACA,UAII,CAAC,GACsB;AAC3B,QAAM,WAAW,KAAK,IAAI,MAAM,QAAQ,YAAY,+BAA+B;AACnF,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,YAAY,+BAA+B,CAAC;AAC5F,QAAM,OAAO;AACb,QAAM,WAA2B,CAAC;AAClC,MAAI,QAAQ;AACZ,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,QAAQ,cAAc,WAAW,KAAK,SAAS,IAAI;AACzD,QAAM,MAAM,cAAc,WAAW,KAAK,IAAI,IAAI,KAAK,SAAS,WAAW,CAAC,IAAI,KAAK;AACrF,QAAM,OAAO,cAAc,WAAW,KAAK;AAC3C,WAAS,QAAQ,OAAO,UAAU,OAAO,SAAS,SAAS,UAAU,SAAS,MAAM;AAClF,UAAM,QAAQ,KAAK,KAAK;AACxB,UAAM,aAAa,iBAAiB,KAAK;AACzC,UAAM,YAAY,SAAS,WAAW,IAAI,IAAI;AAC9C,QAAI,SAAS,SAAS,KAAK,QAAQ,YAAY,aAAa,SAAU;AACtE,aAAS,KAAK,KAAK;AACnB,aAAS,YAAY;AAAA,EACvB;AACA,MAAI,cAAc,SAAU,UAAS,QAAQ;AAC7C,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,WAAW,SAAS,SAAS,KAAK;AAAA,EACpC;AACF;AAGO,SAAS,gCACd,SACA,OACA,UAAoD,CAAC,GAC1B;AAC3B,QAAM,WAAW,KAAK,IAAI,MAAM,QAAQ,YAAY,+BAA+B;AACnF,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,YAAY,+BAA+B,CAAC;AAC5F,QAAM,SAAS,CAAC,GAAG,QAAQ,QAAQ,GAAG,KAAK;AAC3C,MAAI,QAAQ,QAAQ;AACpB,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,aAAS,iBAAiB,MAAM,KAAK,CAAC,KAAK,QAAQ,OAAO,SAAS,QAAQ,IAAI,IAAI;AAAA,EACrF;AACA,MAAI,QAAQ;AAGZ,SAAO,OAAO,SAAS,QAAQ,MAAM,QAAQ,YAAY,OAAO,SAAS,QAAQ,WAAW;AAC1F,aAAS,iBAAiB,OAAO,KAAK,CAAC,IAAI;AAC3C,aAAS;AAAA,EACX;AACA,SAAO;AAAA,IACL,QAAQ,UAAU,IAAI,SAAS,OAAO,MAAM,KAAK;AAAA,IACjD;AAAA,IACA,WAAW,QAAQ,aAAa,QAAQ;AAAA,EAC1C;AACF;AAEA,SAAS,iBAAiB,OAAwB;AAChD,SAAO,QAAQ,OAAO,KAAK,UAAU,KAAK,CAAC,EAAE;AAC/C;AAEA,SAAS,qBACP,QACA,KAC2B;AAC3B,MAAI,SAA6D;AACjE,aAAW,SAAS,QAAQ;AAC1B,UAAM,SAAS,wBAAwB,CAAC,KAAK,CAAC;AAC9C,QAAI,WAAW,CAAC,UAAU,MAAM,YAAY,OAAO,WAAW;AAC5D,eAAS,EAAE,UAAU,MAAM,UAAU,OAAO;AAAA,IAC9C;AAAA,EACF;AACA,MAAI,CAAC,UAAU,OAAO,WAAW,IAAI,QAAQ,SAAU,QAAO;AAC9D,MAAI,UAAU;AACd,SAAO,OAAO;AAChB;AAiBA,eAAe,sBACb,QACA,aACA,WACA,QACA,UAAoC,CAAC,GACL;AAChC,MAAI,QAAQ,QAAQ,QAAS,OAAM,WAAW;AAC9C,QAAM,UAAU,MAAM,OAAO,WAAW,aAAa,WAAW;AAAA,IAC9D,OAAO;AAAA,IACP,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACrD,CAAC;AACD,MAAI,QAAQ,QAAQ,QAAS,OAAM,WAAW;AAC9C,QAAM,cAAc,KAAK,IAAI,QAAQ,QAAQ,YAAY;AACzD,QAAM,SAAS,cAAc;AAC7B,MAAI,UAAU,wCAAwC;AACpD,WAAO,EAAE,MAAM,SAAS;AAAA,EAC1B;AACA,MAAI,SAAS,wCAAwC;AACnD,WAAO,EAAE,MAAM,SAAS;AAAA,EAC1B;AAEA,QAAM,OAAO,MAAM,aAAa,QAAQ,aAAa,WAAW,QAAQ;AAAA,IACtE,UAAU;AAAA,IACV,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACrD,CAAC;AACD,QAAM,SAAS,KAAK,OAAO,CAAC,UAAU,oBAAoB,KAAK,IAAI,MAAM;AACzE,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO,EAAE,MAAM,SAAS;AAAA,EAC1B;AACA,kBAAgB,MAAM;AACtB,QAAM,iBAAiB,kBAAkB,MAAM;AAC/C,MAAI,iBAAiB,aAAa;AAGhC,WAAO,EAAE,MAAM,SAAS;AAAA,EAC1B;AACA,MACE,OAAO,SAAS,yCAChB,WAAW,MAAM,IAAI,yCACrB,iBAAiB,MAAM,IAAI,sCAC3B;AACA,WAAO,EAAE,MAAM,SAAS;AAAA,EAC1B;AACA,SAAO,EAAE,MAAM,UAAU,QAAQ,eAAe;AAClD;AAgBA,eAAe,gBACb,QACA,aACA,WACA,SAS4B;AAC5B,MAAI,SAAS,QAAQ;AACrB,MAAI,SAAyB,CAAC;AAC9B,MAAI,eAAe;AACnB,MAAI,UAAU;AAEd,SAAO,UAAU,QAAQ,YAAY;AACnC,QAAI,OAAO,SAAS,KAAK,WAAW,MAAM,KAAK,QAAQ,cAAc;AACnE;AAAA,IACF;AACA,UAAM,OAAO,MAAM,iBAAiB,QAAQ,aAAa,WAAW,QAAQ;AAAA,MAC1E,UAAU,QAAQ;AAAA,MAClB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACrD,CAAC;AACD,QAAI,QAAQ,YAAY,MAAM,MAAO,OAAM,WAAW;AACtD,eAAW;AACX,QAAI,KAAK,WAAW,GAAG;AACrB,qBAAe;AACf;AAAA,IACF;AACA,oBAAgB,IAAI;AACpB,aAAS,CAAC,GAAG,MAAM,GAAG,MAAM;AAC5B,aAAS,KAAK,CAAC,EAAG;AAClB,QAAI,WAAW,KAAK,CAAC,CAAE,GAAG;AACxB,qBAAe;AACf;AAAA,IACF;AAAA,EACF;AAQA,MAAI,YAAY;AAChB,SACE,CAAC,gBACD,kBAAkB,MAAM,MAAM,MAC9B,aAAa,QAAQ,mBAAmB,IACxC;AACA,UAAM,OAAO,MAAM,iBAAiB,QAAQ,aAAa,WAAW,QAAQ;AAAA,MAC1E,UAAU,QAAQ;AAAA,MAClB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACrD,CAAC;AACD,QAAI,QAAQ,YAAY,MAAM,MAAO,OAAM,WAAW;AACtD,eAAW;AACX,iBAAa;AACb,QAAI,KAAK,WAAW,GAAG;AACrB,qBAAe;AACf;AAAA,IACF;AACA,oBAAgB,IAAI;AACpB,aAAS,CAAC,GAAG,MAAM,GAAG,MAAM;AAC5B,aAAS,KAAK,CAAC,EAAG;AAClB,QAAI,WAAW,KAAK,CAAC,CAAE,GAAG;AACxB,qBAAe;AACf;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,cAAc;AACjB,UAAM,WAAW,kBAAkB,MAAM;AACzC,QAAI,WAAW,GAAG;AAChB,eAAS,OAAO,MAAM,QAAQ;AAAA,IAChC;AAAA,EACF;AACA,QAAM,gBAAgB,0BAA0B,QAAQ,QAAQ,YAAY;AAC5E,WAAS,cAAc;AAEvB,QAAM,SAAS,OAAO,CAAC,KAAK;AAC5B,QAAM,SAAS,OAAO,OAAO,SAAS,CAAC,KAAK;AAC5C,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB,QAAQ,YAAY;AAAA,IACpC,gBAAgB,SAAS,kBAAkB,MAAM,IAAI;AAAA,IACrD,UACE,OAAO,SAAS,MACf,cAAc,WAAY,CAAC,gBAAgB,QAAQ,SAAS;AAAA,EACjE;AACF;AAGA,SAAS,kBAAkB,QAAgC;AACzD,WAAS,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAAG;AACrD,QAAI,eAAe,OAAO,KAAK,CAAE,GAAG;AAClC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAA8B;AACpD,SAAO,MAAM,SAAS,qBAAqB,MAAM,SAAS;AAC5D;AAMA,eAAe,uBACb,QACA,aACA,WACA,SAQmC;AACnC,MAAI,SAAS,QAAQ;AACrB,MAAI,SAAyB,CAAC;AAC9B,MAAI,UAAU;AACd,MAAI,aAAa;AAEjB,SAAO,UAAU,QAAQ,YAAY;AACnC,QAAI,OAAO,SAAS,KAAK,WAAW,MAAM,KAAK,QAAQ,cAAc;AACnE;AAAA,IACF;AACA,UAAM,OAAO,MAAM,aAAa,QAAQ,aAAa,WAAW,QAAQ;AAAA,MACtE,UAAU,QAAQ;AAAA,MAClB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACrD,CAAC;AACD,QAAI,QAAQ,YAAY,MAAM,MAAO,OAAM,WAAW;AACtD,eAAW;AACX,QAAI,KAAK,WAAW,GAAG;AACrB,mBAAa;AACb;AAAA,IACF;AACA,oBAAgB,IAAI;AACpB,aAAS,CAAC,GAAG,QAAQ,GAAG,IAAI;AAM5B,aAAS,kBAAkB,IAAI;AAAA,EACjC;AACA,QAAM,gBAAgB,yBAAyB,QAAQ,QAAQ,YAAY;AAC3E,WAAS,cAAc;AAEvB,QAAM,SAAS,OAAO,CAAC,KAAK;AAC5B,QAAM,SAAS,OAAO,OAAO,SAAS,CAAC,KAAK;AAC5C,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,gBAAgB,QAAQ,YAAY;AAAA,IACpC,gBAAgB,SAAS,kBAAkB,MAAM,IAAI;AAAA,IACrD,UAAU,OAAO,SAAS,MAAM,cAAc,WAAW,CAAC;AAAA,EAC5D;AACF;AAQA,SAAS,0BAA0B,QAAwB,cAAqC;AAC9F,MAAI,CAAC,OAAO,SAAS,YAAY,KAAK,gBAAgB,KAAK,OAAO,WAAW,GAAG;AAC9E,WAAO,EAAE,QAAQ,SAAS,MAAM;AAAA,EAClC;AACA,WAAS,QAAQ,OAAO,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG;AACzD,QAAI,CAAC,eAAe,OAAO,KAAK,CAAE,EAAG;AACrC,UAAM,YAAY,OAAO,MAAM,KAAK;AACpC,QAAI,WAAW,SAAS,KAAK,cAAc;AACzC,aAAO,EAAE,QAAQ,WAAW,SAAS,KAAK;AAAA,IAC5C;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,SAAS,MAAM;AAClC;AAGA,SAAS,yBAAyB,QAAwB,cAAqC;AAC7F,MAAI,CAAC,OAAO,SAAS,YAAY,KAAK,gBAAgB,KAAK,OAAO,WAAW,GAAG;AAC9E,WAAO,EAAE,QAAQ,SAAS,MAAM;AAAA,EAClC;AACA,WAAS,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAAG;AACrD,QAAI,CAAC,eAAe,OAAO,KAAK,CAAE,EAAG;AACrC,UAAM,YAAY,OAAO,MAAM,GAAG,KAAK;AACvC,QAAI,WAAW,SAAS,KAAK,cAAc;AACzC,aAAO,EAAE,QAAQ,WAAW,SAAS,KAAK;AAAA,IAC5C;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,SAAS,MAAM;AAClC;AAIA,eAAe,iBACb,QACA,aACA,WACA,QACA,SAIuB;AACvB,MAAI,QAAQ,QAAQ,SAAS;AAC3B,UAAM,WAAW;AAAA,EACnB;AACA,QAAM,YAAY,QAAQ;AAC1B,MAAI,cAAc,GAAG;AACnB,WAAO,OAAO,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC;AAAA,EACxC;AACA,QAAM,OAAO,MAAM,OAAO,WAAW,aAAa,WAAW;AAAA,IAC3D;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,IAKT,aAAa;AAAA,EACf,CAAC;AACD,MAAI,QAAQ,QAAQ,SAAS;AAC3B,UAAM,WAAW;AAAA,EACnB;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,UAAU,CAAC;AAC1C;AAEA,eAAe,aACb,QACA,aACA,WACA,OACA,SAIuB;AACvB,MAAI,QAAQ,QAAQ,SAAS;AAC3B,UAAM,WAAW;AAAA,EACnB;AACA,QAAM,YAAY,QAAQ;AAC1B,MAAI,cAAc,GAAG;AACnB,WAAO,OAAO,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC;AAAA,EACxC;AACA,QAAM,OAAO,MAAM,OAAO,WAAW,aAAa,WAAW;AAAA,IAC3D;AAAA,IACA,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,EACf,CAAC;AACD,MAAI,QAAQ,QAAQ,SAAS;AAC3B,UAAM,WAAW;AAAA,EACnB;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,UAAU,CAAC;AAC1C;AAEA,SAAS,WAAW,QAAgC;AAClD,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AACA,SAAO,cAAc,cAAc,MAAM,CAAC,EAAE;AAC9C;AAEA,SAAS,WAAW,OAA8B;AAChD,SAAO,MAAM,SAAS,qBAAqB,MAAM,YAAY;AAC/D;AAEA,SAAS,kBAAkB,QAAyC;AAClE,SAAO,OAAO,OAAO,CAAC,KAAK,UAAU,KAAK,IAAI,KAAK,oBAAoB,KAAK,CAAC,GAAG,CAAC;AACnF;AAEA,SAAS,wBAAwB,QAAgD;AAC/E,SAAO,OAAO,SAAS,IAAI,kBAAkB,MAAM,IAAI;AACzD;AAEA,SAAS,oBAAoB,OAA6B;AACxD,QAAM,mBAAmB,iCAAiC,KAAK;AAC/D,MAAI,qBAAqB,KAAM,QAAO;AACtC,SAAO,OAAO,MAAM,mBAAmB,YACrC,OAAO,cAAc,MAAM,cAAc,KACzC,MAAM,kBAAkB,MAAM,WAC5B,MAAM,iBACN,MAAM;AACZ;AAEA,SAAS,gBAAgB,QAA8B;AACrD,WAAS,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAAG;AACrD,QAAI,OAAO,QAAQ,CAAC,EAAG,YAAY,OAAO,KAAK,EAAG,UAAU;AAC1D,YAAM,IAAI,MAAM,uEAAuE;AAAA,IACzF;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,UAA0B,OAA6B;AACjF,MAAI,CAAC,wBAAwB,KAAK,SAAS,WAAW,KAAK,MAAM,WAAW,GAAG;AAC7E;AAAA,EACF;AACA,MAAI,MAAM,MAAM,SAAS,CAAC,EAAG,YAAY,SAAS,CAAC,EAAG,UAAU;AAC9D,UAAM,IAAI,MAAM,gEAAgE;AAAA,EAClF;AACF;AAEA,SAAS,kBAAkB,UAA0B,OAA6B;AAChF,MAAI,CAAC,wBAAwB,KAAK,SAAS,WAAW,KAAK,MAAM,WAAW,GAAG;AAC7E;AAAA,EACF;AACA,MAAI,MAAM,CAAC,EAAG,YAAY,SAAS,SAAS,SAAS,CAAC,EAAG,UAAU;AACjE,UAAM,IAAI,MAAM,gEAAgE;AAAA,EAClF;AACF;AAEA,SAAS,0BAAmC;AAC1C,QAAM,aAAc,WAA6D,SAAS;AAC1F,SAAO,eAAe,UAAa,WAAW,aAAa;AAC7D;AAEA,SAAS,aAAoB;AAC3B,QAAM,QAAQ,IAAI,MAAM,4BAA4B;AACpD,QAAM,OAAO;AACb,SAAO;AACT;;;AChlDA,SAAS,eAAAA,cAAa,aAAAC,YAAW,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,iBAAgB;AAmC3D,SAAS,aAAa,OAA4C;AACvE,SAAO,MAAM,SAAS;AACxB;AAEA,SAAS,qBAAqB,OAA4C;AACxE,SACE,aAAa,KAAK,KAClB,MAAM,KAAK,WAAW,kBAAkB,KACxC,MAAM,KAAK,WAAW,eAAe,KACrC,MAAM,SAAS,4BACf,MAAM,SAAS;AAEnB;AAGO,SAAS,WACd,WACA,UAA6B,CAAC,GACZ;AAClB,QAAM,EAAE,QAAQ,aAAa,uBAAuB,0BAA0B,IAC5E,uBAAuB,OAAO;AAChC,QAAM,WAAW,QAAQ,WAAW,SAAS,QAAQ,SAAS;AAC9D,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAyB,IAAI;AAC7D,QAAM,mBAAmBC,QAAO,CAAC;AACjC,QAAM,qBAAqBA,QAAO,CAAC;AACnC,QAAM,YAAY,QAAQ;AAC1B,QAAM,EAAE,KAAK,UAAU,eAAe,mBAAmB,IAAI,kBAAkB;AAC/E,QAAM,OAAOC;AAAA,IACX,OAAO,WAAyB;AAC9B,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,UAAIC,kBAAiB;AACrB,YAAM,UAAU,MAAM,OAAO,WAAW,aAAa,WAAW;AAAA,QAC9D,OAAO;AAAA,QACP;AAAA,QACA,gBAAgB,MAAM;AACpB,UAAAA,kBAAiB,YAAY,KAAK,EAAE,mBAAmB;AAAA,QACzD;AAAA,MACF,CAAC;AAED,kBAAY,IAAI;AAChB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU,EAAE,iBAAiB;AAAA,QAC7B,gBAAAA;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,WAAW,QAAQ,aAAa,SAAS;AAAA,EAC5C;AACA,QAAM,EAAE,MAAM,SAAS,OAAO,QAAQ,IAAI,eAAe,MAAM;AAAA,IAC7D,gBAAgB,QAAQ;AAAA,IACxB;AAAA,EACF,CAAC;AACD,EAAAC,WAAU,MAAM;AACd,QAAI,WAAW,sBAAuB,MAAK,QAAQ;AAAA,EACrD,GAAG,CAAC,SAAS,SAAS,qBAAqB,CAAC;AAC5C,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,aAAa,CAAC,QAAS;AAC5B,WAAO,0BAA0B,WAAW,WAAW,OAAO;AAAA,EAChE,GAAG,CAAC,SAAS,SAAS,2BAA2B,SAAS,CAAC;AAE3D,QAAM,OAAO,MAAM,WAAW;AAC9B,QAAM,eAAe,MAAM,YAAY;AACvC,QAAM,iBAAiB,MAAM,kBAAkB;AAG/C,QAAM,UAAUC;AAAA,IACd,MACE,QAAQ,YAAY,SAAS,OAAO,KAAK,KACrC,EAAE,GAAG,MAAM,OAAO,SAAS,OAAO,aAAa,SAAS,YAAY,IACpE;AAAA,IACN,CAAC,MAAM,QAAQ;AAAA,EACjB;AAEA,QAAM,eAAe,QAAQ;AAI7B,QAAM,eAAeH;AAAA,IACnB,CAAC,UAAwB;AAGvB,UACE,cAAc;AAAA,QACZ,CAAC,SACC,KAAK,cAAc,aACnB,CAAC,aAAa,IAAI,KAClB,qBAAqB,IAAI,KACzB,KAAK,YAAY,MAAM,gBAAgB;AAAA,MAC3C,GACA;AACA,aAAK,QAAQ;AAAA,MACf,WAAW,CAAC,aAAa,KAAK,GAAG;AAC/B,YAAI,CAAC,QAAQ,MAAM,WAAW,KAAK,aAAc,MAAK,QAAQ;AAC9D;AAAA,MACF;AAKA,UAAI,CAAC,QAAQ,MAAM,YAAY,KAAK,cAAc;AAChD;AAAA,MACF;AACA,YAAM,UAAW,MAAM,WAAW,CAAC;AACnC,YAAM,QAAQ,QAAQ;AACtB,UAAI,OAAO,UAAU,UAAU;AAC7B;AAAA,MACF;AACA,YAAM,SACJ,QAAQ,WAAW,UAAU,QAAQ,WAAW,UAAU,QAAQ,SAAS;AAC7E,kBAAY,CAAC,YAA4B;AACvC,cAAM,OAAO,WAAW;AACxB,eAAO,EAAE,GAAG,MAAM,OAAO,aAAa,OAAO;AAAA,MAC/C,CAAC;AAAA,IACH;AAAA,IACA,CAAC,MAAM,SAAS,cAAc,SAAS;AAAA,EACzC;AACA,yBAAuB,QAAQ,aAAa,WAAW,sBAAsB,cAAc;AAAA,IACzF;AAAA,IACA,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACnE,CAAC;AAED,QAAM,cAAcA;AAAA,IAClB,OAAO,UAA2C;AAChD,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,YAAM,SAAS,MAAM,IAAI,MAAM,OAAO,cAAc,aAAa,WAAW,EAAE,MAAM,CAAC,CAAC;AACtF,UAAI,QAAQ;AACV,oBAAY,MAAM;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,GAAG;AAAA,EACtC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,EACF;AACF;;;AC/KA,SAAS,eAAAI,cAAa,aAAAC,YAAW,iBAAiB,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,iBAAgB;AAW5E,SAAS,iBAAiB,OAA4C;AAC3E,SACE,MAAM,KAAK,WAAW,OAAO,KAC7B,MAAM,KAAK,WAAW,gBAAgB,KACtC,MAAM,KAAK,WAAW,kBAAkB,KACxC,MAAM,KAAK,WAAW,gBAAgB,KACtC,MAAM,KAAK,WAAW,sBAAsB;AAEhD;AAEA,SAAS,oBACP,WACA,UACS;AACT,SAAO;AAAA,IACL,aACA,UAAU,WAAW,SAAS,WAC9B,UAAU,iBAAiB,kBAAkB,SAAS,iBAAiB;AAAA,EACzE;AACF;AAGA,IAAM,wBAAqE,CAAC;AAyDrE,SAAS,aACd,WACA,UAA+B,CAAC,GACZ;AACpB,QAAM,EAAE,QAAQ,aAAa,uBAAuB,0BAA0B,IAC5E,mBAAmB,OAAO;AAC5B,QAAM,WAAW,QAAQ,WAAW,SAAS,QAAQ,SAAS;AAC9D,QAAM,YAAY,GAAG,WAAW,KAAS,aAAa,EAAE;AACxD,QAAM,WAAW,oBAAoB;AACrC,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAsC,IAAI;AAC1E,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAAS,SAAS;AAC9D,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,OAAO;AAC9C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AACrD,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAAuB,IAAI;AACrE,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAA4C,CAAC,CAAC;AACxF,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAA+B,CAAC,CAAC;AAC7E,QAAM,aAAaC,QAA0C,CAAC,CAAC;AAC/D,QAAM,iBAAiBA,QAAO,CAAC;AAC/B,QAAM,eAAeA,QAAO,SAAS;AACrC,QAAM,cAAcA,QAAoC,IAAI;AAI5D,kBAAgB,MAAM;AACpB,QAAI,aAAa,YAAY,UAAW;AACxC,iBAAa,UAAU;AACvB,mBAAe,WAAW;AAC1B,gBAAY,UAAU;AACtB,eAAW,UAAU,CAAC;AACtB,sBAAkB,SAAS;AAC3B,gBAAY,IAAI;AAChB,eAAW,OAAO;AAClB,aAAS,IAAI;AACb,qBAAiB,IAAI;AACrB,qBAAiB,CAAC,CAAC;AACnB,sBAAkB,CAAC,CAAC;AAAA,EACtB,GAAG,CAAC,SAAS,SAAS,CAAC;AAEvB,EAAAC,WAAU,MAAM;AACd,QAAI,eAAe,WAAW,KAAK,QAAQ,WAAW,OAAW;AACjE,UAAM,wBAAwB,IAAI;AAAA,MAChC,QAAQ,OAAO;AAAA,QAAQ,CAAC,UACtB,MAAM,SAAS,kBAAkB,MAAM,SAAS,CAAC,MAAM,MAAM,IAAI,CAAC;AAAA,MACpE;AAAA,IACF;AACA,QAAI,sBAAsB,SAAS,EAAG;AAKtC;AAAA,MAAkB,CAAC,YACjB,QAAQ,OAAO,CAAC,UAAU,CAAC,sBAAsB,IAAI,MAAM,MAAM,CAAC;AAAA,IACpE;AAAA,EACF,GAAG,CAAC,eAAe,QAAQ,QAAQ,MAAM,CAAC;AAE1C,QAAM,iBAAiBC;AAAA,IACrB,CAAC,gBAAwB,SAA+C;AACtE,UAAI,aAAa,YAAY,eAAgB,QAAO;AACpD,YAAM,UAAU,YAAY;AAC5B,UACE,QACA,YACC,KAAK,UAAU,QAAQ,WACtB,KAAK,iBAAiB,iBAAiB,QAAQ,iBAAiB,iBAClE;AACA,eAAO;AAAA,MACT;AACA,kBAAY,UAAU;AACtB,wBAAkB,cAAc;AAChC,kBAAY,IAAI;AAChB,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,OAAOA;AAAA,IACX,OAAO,kBAAkB,UAAyB;AAChD,UAAI,CAAC,UAAW;AAChB,YAAM,iBAAiB,GAAG,WAAW,KAAS,SAAS;AACvD,YAAM,SAAS,EAAE,eAAe;AAChC,UAAI;AACF,cAAM,UAAU,MAAM,OAAO,SAAS,aAAa,SAAS;AAC5D,YAAI,aAAa,YAAY,eAAgB;AAC7C,cAAM,iBAAiB,WAAW,eAAe;AACjD,YAAI,iBAAiB;AACnB,gBAAM,YAAY,eAAe,gBAAgB,OAAO;AACxD,cAAI,CAAC,aAAa,CAAC,oBAAoB,YAAY,SAAS,OAAO,GAAG;AACpE,kBAAM,IAAI,UAAU,yDAAyD;AAAA,UAC/E;AACA,mBAAS,IAAI;AACb,cAAI,eAAgB,YAAW,KAAK;AAAA,QACtC,WAAW,gBAAgB;AACzB,yBAAe,gBAAgB,OAAO;AACtC,mBAAS,IAAI;AACb,qBAAW,KAAK;AAAA,QAClB;AAAA,MACF,SAAS,OAAO;AACd,YACE,aAAa,YAAY,mBACxB,WAAW,eAAe,WAAW,kBACtC;AACA,mBAAS,QAAQ,KAAK,CAAC;AACvB,cAAI,WAAW,eAAe,QAAS,YAAW,KAAK;AAAA,QACzD;AACA,YAAI,gBAAiB,OAAM;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,cAAc;AAAA,EACjD;AAEA,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,UAAU;AACzB,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,eAAW,IAAI;AACf,UAAM,iBAAiB,QAAQ;AAC/B,QAAI,mBAAmB,UAAa,kBAAkB,GAAG;AACvD,WAAK,KAAK;AACV,aAAO,MAAM;AACX,uBAAe,WAAW;AAAA,MAC5B;AAAA,IACF;AACA,QAAI,YAAY;AAChB,QAAI,QAA8C;AAClD,UAAM,WAAW,MAAM;AACrB,UAAI,UAAW;AACf,cAAQ,WAAW,MAAM;AACvB,gBAAQ;AACR,aAAK,KAAK,EAAE,QAAQ,QAAQ;AAAA,MAC9B,GAAG,cAAc;AAAA,IACnB;AACA,SAAK,KAAK,EAAE,QAAQ,QAAQ;AAC5B,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,UAAU,KAAM,cAAa,KAAK;AACtC,qBAAe,WAAW;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,MAAM,SAAS,UAAU,QAAQ,cAAc,CAAC;AAEpD,EAAAA,WAAU,MAAM;AACd,QAAI,WAAW,sBAAuB,MAAK,KAAK;AAAA,EAClD,GAAG,CAAC,SAAS,MAAM,qBAAqB,CAAC;AACzC,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,aAAa,CAAC,QAAS;AAC5B,WAAO,0BAA0B,WAAW,SAAS,IAAI;AAAA,EAC3D,GAAG,CAAC,SAAS,MAAM,2BAA2B,SAAS,CAAC;AAExD,QAAM,kBAAkB,qBAAqB,MAAM,KAAK,KAAK,CAAC;AAC9D;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE;AAAA,MACA,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACnE;AAAA,IACA,YAAY,MAAM,KAAK,IAAI;AAAA,EAC7B;AAEA,QAAM,SAASC;AAAA,IACb,OACE,QACA,MACA,YAKiD;AACjD,YAAM,iBAAiB;AACvB,UAAI,CAAC,aAAa,aAAa,YAAY,kBAAkB,WAAW,QAAQ,MAAM,GAAG;AACvF,eAAO;AAAA,MACT;AACA,YAAM,UAAU,YAAY;AAC5B,YAAM,OAAO,SAAS,MAAM,KAAK,CAAC,cAAc,UAAU,OAAO,MAAM;AACvE,UAAI,CAAC,WAAW,CAAC,KAAM,QAAO;AAC9B,iBAAW,UAAU,EAAE,GAAG,WAAW,SAAS,CAAC,MAAM,GAAG,KAAK;AAC7D,wBAAkB,cAAc;AAChC,uBAAiB,WAAW,OAAO;AACnC,uBAAiB,IAAI;AACrB,YAAM,gBAAgB,aAAa;AACnC,UAAI;AACF,YAAI;AACJ,YAAI;AACF,mBAAS,MAAM,QAAQ,SAAS,MAAM,aAAa;AAAA,QACrD,SAAS,OAAO;AACd,cAAI,CAAC,sBAAsB,KAAK,EAAG,OAAM;AAGzC,mBAAS,MAAM,QAAQ,SAAS,MAAM,aAAa;AAAA,QACrD;AACA,YAAI,aAAa,YAAY,eAAgB,QAAO;AACpD,uBAAe,gBAAgB,OAAO,QAAQ;AAC9C,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,aAAa,YAAY,gBAAgB;AAC3C,2BAAiB,QAAQ,KAAK,CAAC;AAC/B,gBAAM,KAAK;AAAA,QACb;AACA,eAAO;AAAA,MACT,UAAE;AACA,YAAI,aAAa,YAAY,kBAAkB,UAAU,WAAW,SAAS;AAC3E,gBAAM,OAAO,EAAE,GAAG,WAAW,QAAQ;AACrC,iBAAO,KAAK,MAAM;AAClB,qBAAW,UAAU;AACrB,2BAAiB,IAAI;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,gBAAgB,MAAM,WAAW,SAAS;AAAA,EAC7C;AAEA,QAAM,WAAWA;AAAA,IACf,OAAO,QAAgB,iBAAkD;AACvE,YAAM,SAAS,MAAM;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAQ,CAAC,SAAS,OAAO,kBAC3D,OAAO,cAAc,aAAa,WAAY,QAAQ;AAAA,UACpD;AAAA,UACA,sBAAsB,QAAQ;AAAA,UAC9B;AAAA,QACF,CAAC;AAAA,MACH;AACA,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,CAAC,QAAQ,QAAQ,WAAW,WAAW;AAAA,EACzC;AAEA,QAAM,WAAWA;AAAA,IACf,OACE,QACA,SACkC;AAClC,YAAM,SAAS,MAAM;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAQ,CAAC,UAAU,MAAM,kBAC3D,OAAO,cAAc,aAAa,WAAY,QAAQ;AAAA,UACpD;AAAA,UACA,qBAAqB,KAAK;AAAA,UAC1B,uBAAuB,KAAK;AAAA,UAC5B,cAAc,KAAK;AAAA,QACrB,CAAC;AAAA,MACH;AACA,aAAO,QAAQ,SAAS;AAAA,IAC1B;AAAA,IACA,CAAC,QAAQ,QAAQ,WAAW,WAAW;AAAA,EACzC;AAEA,QAAM,YAAYA;AAAA,IAChB,OAAO,WAAqC;AAC1C,YAAM,iBAAiB;AACvB,YAAM,OAAO,YAAY,SAAS,MAAM,KAAK,CAAC,cAAc,UAAU,OAAO,MAAM;AACnF,UAAI,aAAa,YAAY,eAAgB,QAAO;AACpD,UAAI,CAAC,MAAM;AACT,yBAAiB,IAAI,MAAM,wDAAwD,CAAC;AACpF,cAAM,KAAK;AACX,eAAO;AAAA,MACT;AACA,YAAM,aAAiC;AAAA,QACrC,QAAQ,KAAK;AAAA,QACb,gBAAgB,KAAK;AAAA,QACrB,MAAM,KAAK;AAAA,QACX,aAAa,KAAK,eAAe,CAAC;AAAA,QAClC,WAAW,KAAK;AAAA,QAChB,OAAO,KAAK;AAAA,QACZ,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,QACnC,OAAO;AAAA,MACT;AACA,wBAAkB,CAAC,YAAY;AAAA,QAC7B,GAAG,QAAQ,OAAO,CAAC,UAAU,MAAM,WAAW,MAAM;AAAA,QACpD;AAAA,MACF,CAAC;AACD,YAAM,SAAS,MAAM;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAS,CAAC,SAAS,YAAY,kBACjE,OAAO,eAAe,aAAa,WAAY,QAAQ;AAAA,UACrD;AAAA,UACA,qBAAqB,WAAW;AAAA,UAChC,aAAa,QAAQ,iBAAiB;AAAA,QACxC,CAAC;AAAA,MACH;AACA,UAAI,aAAa,YAAY,eAAgB,QAAO;AAKpD,YAAM,uBACJ,WAAW,QACX,YAAY,YAAY,QACxB,CAAC,YAAY,QAAQ,MAAM,KAAK,CAAC,cAAc,UAAU,OAAO,MAAM;AACxE,UAAI,sBAAsB;AACxB,yBAAiB,IAAI;AACrB,0BAAkB,CAAC,YAAY,QAAQ,OAAO,CAAC,UAAU,MAAM,WAAW,MAAM,CAAC;AACjF,eAAO;AAAA,MACT;AACA,YAAM,WACJ,WAAW,QACX,YAAY,SAAS,MAAM;AAAA,QACzB,CAAC,cAAc,UAAU,OAAO,UAAU,UAAU,SAAS,aAAa;AAAA,MAC5E,MAAM;AACR;AAAA,QAAkB,CAAC,YACjB,WACI,QAAQ;AAAA,UAAI,CAAC,UACX,MAAM,WAAW,SAAS,EAAE,GAAG,OAAO,OAAO,SAAkB,IAAI;AAAA,QACrE,IACA,QAAQ,OAAO,CAAC,UAAU,MAAM,WAAW,MAAM;AAAA,MACvD;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,MAAM,QAAQ,WAAW,WAAW,WAAW;AAAA,EAC1D;AAEA,QAAM,aAAaA;AAAA,IACjB,OAAO,WAAqC;AAC1C,YAAM,SAAS,MAAM;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAU,CAAC,UAAU,MAAM,kBAC7D,OAAO,gBAAgB,aAAa,WAAY,QAAQ;AAAA,UACtD;AAAA,UACA,qBAAqB,KAAK;AAAA,UAC1B,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AACA,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,CAAC,QAAQ,QAAQ,WAAW,WAAW;AAAA,EACzC;AAEA,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,kBAAkB,kBAAkB,WAAW;AACrD,QAAM,uBAAuB,kBAAkB,gBAAgB;AAC/D,QAAM,WAAWC;AAAA,IACf,MAAM,OAAO,KAAK,oBAAoB,EAAE,SAAS;AAAA,IACjD,CAAC,oBAAoB;AAAA,EACvB;AACA,QAAM,cAAcD;AAAA,IAClB,CAAC,WAA6C,qBAAqB,MAAM,KAAK;AAAA,IAC9E,CAAC,oBAAoB;AAAA,EACvB;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO,iBAAiB,SAAS,CAAC;AAAA,IAClC,eAAe,iBAAiB,iBAAiB,CAAC;AAAA,IAClD,wBAAwB,iBAAiB,0BAA0B;AAAA,IACnE,2BAA2B,iBAAiB,6BAA6B,CAAC;AAAA,IAC1E,kBAAkB,iBAAiB,oBAAoB;AAAA,IACvD,yBAAyB,iBAAiB,2BAA2B;AAAA,IACrE,SAAS,kBAAkB,UAAU;AAAA,IACrC,OAAO,kBAAkB,QAAQ;AAAA,IACjC,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA,eAAe,kBAAkB,gBAAgB;AAAA,IACjD,oBAAoBA,aAAY,MAAM;AACpC,UAAI,aAAa,YAAY,UAAW,kBAAiB,IAAI;AAAA,IAC/D,GAAG,CAAC,SAAS,CAAC;AAAA,IACd,gBAAgB,kBAAkB,iBAAiB,CAAC;AAAA,EACtD;AACF;AAEA,SAAS,eAAuB;AAC9B,SAAO,WAAW,OAAO,WAAW;AACtC;AAEA,SAAS,QAAQ,OAAuB;AACtC,SAAO,eAAe,KAAK;AAC7B;AAEA,SAAS,sBAAsB,OAAyB;AACtD,SACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAuC,mBAAmB;AAE/D;;;ACtdA,SAAS,eAAAE,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAelD,SAAS,kBAAkB,OAA4C;AAC5E,SACE,MAAM,SAAS,kCACf,MAAM,SAAS,6BACf,MAAM,SAAS,oBACf,MAAM,SAAS,iBACf,MAAM,SAAS;AAEnB;AA4BO,SAAS,sBACd,WACA,UAAwC,CAAC,GACZ;AAC7B,QAAM,EAAE,QAAQ,aAAa,0BAA0B,IAAI,6BAA6B,OAAO;AAC/F,QAAM,WAAW,QAAQ,WAAW,SAAS,QAAQ,SAAS;AAC9D,QAAM,OAAOC;AAAA,IACX,YACE,YACI,MAAM,OAAO,uBAAuB,aAAa,WAAW,EAAE,QAAQ,UAAU,CAAC,IACjF,CAAC;AAAA,IACP,CAAC,QAAQ,WAAW,WAAW;AAAA,EACjC;AACA,QAAM,QAAQ,eAAe,MAAM;AAAA,IACjC;AAAA,IACA,gBAAgB,QAAQ;AAAA,EAC1B,CAAC;AACD,QAAM,iBAAiB,MAAM;AAC7B,QAAM,kBAAkB,MAAM;AAC9B,QAAM,WAAW,kBAAkB,GAAG,WAAW,KAAS,aAAa,EAAE,EAAE;AAC3E,QAAM,CAAC,qBAAqB,sBAAsB,IAAIC,UAAwB,IAAI;AAClF,QAAM,CAAC,iBAAiB,kBAAkB,IAAIA,UAAS,CAAC;AACxD,QAAM,uBAAuBC,QAAsB,IAAI;AAEvD,EAAAC,WAAU,MAAM;AACd,yBAAqB,UAAU;AAC/B,2BAAuB,IAAI;AAAA,EAC7B,GAAG,CAAC,WAAW,WAAW,CAAC;AAC3B,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,aAAa,CAAC,QAAS;AAC5B,WAAO,0BAA0B,WAAW,eAAe,MAAM,OAAO;AAAA,EAC1E,GAAG,CAAC,SAAS,2BAA2B,WAAW,MAAM,OAAO,CAAC;AAEjE,QAAM,kBAAkB,qBAAqB,MAAM,KAAK,MAAM,QAAQ,CAAC;AACvE,yBAAuB,QAAQ,aAAa,WAAW,mBAAmB,iBAAiB;AAAA,IACzF;AAAA,IACA,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACnE,CAAC;AAED,EAAAA,WAAU,MAAM;AACd,UAAMC,OAAM,KAAK,IAAI;AACrB,UAAM,gBAAgB,kBAAkB,CAAC,GAAG,OAAsB,CAAC,MAAM,YAAY;AACnF,UAAI,QAAQ,WAAW,aAAa,CAAC,QAAQ,UAAW,QAAO;AAC/D,YAAM,WAAW,KAAK,MAAM,QAAQ,SAAS;AAC7C,UAAI,CAAC,OAAO,SAAS,QAAQ,KAAK,YAAYA,KAAK,QAAO;AAC1D,aAAO,SAAS,OAAO,WAAW,KAAK,IAAI,MAAM,QAAQ;AAAA,IAC3D,GAAG,IAAI;AACP,QAAI,iBAAiB,KAAM;AAC3B,UAAM,QAAQ,WAAW;AAAA,MACvB,MAAM;AACJ,2BAAmB,CAAC,YAAY,UAAU,CAAC;AAC3C,aAAK,gBAAgB;AAAA,MACvB;AAAA,MACA,KAAK,IAAI,YAAe,KAAK,IAAI,GAAG,eAAeA,OAAM,CAAC,CAAC;AAAA,IAC7D;AACA,WAAO,MAAM,WAAW,aAAa,KAAK;AAAA,EAC5C,GAAG,CAAC,gBAAgB,eAAe,CAAC;AAEpC,QAAM,UAAUJ;AAAA,IACd,OACE,WACA,aACiC;AACjC,UAAI,CAAC,aAAa,qBAAqB,YAAY,KAAM,QAAO;AAChE,2BAAqB,UAAU;AAC/B,6BAAuB,SAAS;AAChC,UAAI;AACF,cAAM,QAAQ,MAAM,SAAS;AAAA,UAAI,MAC/B,OAAO,yBAAyB,aAAa,WAAW,WAAW,UAAU;AAAA,YAC3E,eAAe,WAAW,OAAO,WAAW;AAAA,UAC9C,CAAC;AAAA,QACH;AACA,YAAI,MAAO,OAAM,MAAM,QAAQ;AAC/B,eAAO;AAAA,MACT,UAAE;AACA,YAAI,qBAAqB,YAAY,WAAW;AAC9C,+BAAqB,UAAU;AAC/B,iCAAuB,IAAI;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,UAAU,WAAW,OAAO,WAAW;AAAA,EAClD;AAEA,QAAM,MAAM,KAAK,IAAI;AACrB,OAAK;AACL,SAAO;AAAA,IACL,UAAU,CAAC,GAAI,MAAM,QAAQ,CAAC,CAAE,EAC7B,OAAO,CAAC,YAAY,8BAA8B,SAAS,GAAG,CAAC,EAC/D;AAAA,MACC,CAAC,MAAM,UACL,KAAK,UAAU,cAAc,MAAM,SAAS,KAAK,KAAK,GAAG,cAAc,MAAM,EAAE;AAAA,IACnF;AAAA,IACF,SAAS,MAAM;AAAA,IACf,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf;AAAA,IACA;AAAA,IACA,eAAe,SAAS;AAAA,IACxB,oBAAoB,SAAS;AAAA,EAC/B;AACF;;;AC5JA,SAAS,eAAAK,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAwFzD,IAAM,UAAU,CAAC,SAAwB,KAAK,KAAK,WAAW,QAAQ;AAEtE,IAAI,uBAAuB;AAE3B,SAAS,qBAA6B;AACpC,QAAM,eAAe,WAAW;AAChC,MAAI,OAAO,cAAc,eAAe,WAAY,QAAO,aAAa,WAAW;AACnF,0BAAwB;AAIxB,SAAO,cAAc,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,qBAAqB,SAAS,EAAE,CAAC;AACnF;AAEA,SAAS,+BAA+B,OAAuD;AAC7F,SAAO,OAAO,UAAU,YACtB,UAAU,QACV,UAAU,SACV,MAAM,SAAS,4BACb,MAAM,OACN;AACN;AAWO,SAAS,mBACd,UAAqC,CAAC,GACZ;AAC1B,QAAM,EAAE,QAAQ,YAAY,IAAI,2BAA2B,OAAO;AAClE,QAAM,cAAc,gBAAgB;AACpC,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,CAAC,aAAa,cAAc,IAAIC,UAA2B,CAAC,CAAC;AACnE,QAAM,iBAAiBC,QAAO,WAAW;AACzC,iBAAe,UAAU;AAGzB,QAAM,UAAUA,QAA0B,oBAAI,IAAI,CAAC;AAInD,QAAM,cAAcA,QAA4B,oBAAI,IAAI,CAAC;AACzD,QAAM,mBAAmBA,QAA4B,oBAAI,IAAI,CAAC;AAC9D,QAAM,4BAA4BA,QAAoB,oBAAI,IAAI,CAAC;AAC/D,QAAM,gBAAgBC,aAAY,CAAC,OAAe;AAChD,UAAM,aAAa,YAAY,QAAQ,IAAI,EAAE;AAC7C,QAAI,CAAC,WAAY;AACjB,SAAK,iBAAiB,QAAQ,IAAI,EAAE,KAAK,KAAK,GAAG;AAC/C,gCAA0B,QAAQ,IAAI,EAAE;AACxC;AAAA,IACF;AACA,gBAAY,QAAQ,OAAO,EAAE;AAC7B,8BAA0B,QAAQ,OAAO,EAAE;AAC3C,QAAI,gBAAgB,UAAU;AAAA,EAChC,GAAG,CAAC,CAAC;AACL,QAAM,oBAAoBA,aAAY,MAAM;AAC1C,eAAW,MAAM,YAAY,QAAQ,KAAK,EAAG,eAAc,EAAE;AAAA,EAC/D,GAAG,CAAC,aAAa,CAAC;AAClB,QAAM,gBAAgBA;AAAA,IACpB,CAAC,OAAyC;AACxC,UAAI,CAAC,YAAY,QAAQ,IAAI,EAAE,EAAG,QAAO;AACzC,uBAAiB,QAAQ,IAAI,KAAK,iBAAiB,QAAQ,IAAI,EAAE,KAAK,KAAK,CAAC;AAC5E,UAAI,WAAW;AACf,aAAO,MAAM;AACX,YAAI,SAAU;AACd,mBAAW;AACX,cAAM,aAAa,iBAAiB,QAAQ,IAAI,EAAE,KAAK,KAAK;AAC5D,YAAI,YAAY,GAAG;AACjB,2BAAiB,QAAQ,IAAI,IAAI,SAAS;AAC1C;AAAA,QACF;AACA,yBAAiB,QAAQ,OAAO,EAAE;AAClC,YAAI,0BAA0B,QAAQ,IAAI,EAAE,EAAG,eAAc,EAAE;AAAA,MACjE;AAAA,IACF;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAKA,QAAM,yBAAyBD,QAAoB,oBAAI,IAAI,CAAC;AAC5D,EAAAE,WAAU,MAAM;AACd,UAAM,aAAa,IAAI,IAAI,YAAY,IAAI,CAAC,eAAe,WAAW,EAAE,CAAC;AACzE,eAAW,MAAM,uBAAuB,SAAS;AAC/C,UAAI,CAAC,WAAW,IAAI,EAAE,EAAG,eAAc,EAAE;AAAA,IAC3C;AACA,2BAAuB,UAAU;AAAA,EACnC,GAAG,CAAC,aAAa,aAAa,CAAC;AAI/B,QAAM,kBAAkBF,QAAO,CAAC;AAChC,QAAM,gBAAgBA,QAAO,EAAE,QAAQ,YAAY,CAAC;AAEpD,EAAAE,WAAU,MAAM;AACd,UAAM,WAAW,cAAc;AAC/B,QAAI,SAAS,WAAW,UAAU,SAAS,gBAAgB,YAAa;AACxE,kBAAc,UAAU,EAAE,QAAQ,YAAY;AAC9C,oBAAgB,WAAW;AAC3B,YAAQ,QAAQ,MAAM;AACtB,sBAAkB;AAClB,mBAAe,CAAC,CAAC;AAAA,EACnB,GAAG,CAAC,QAAQ,mBAAmB,WAAW,CAAC;AAE3C,EAAAA;AAAA,IACE,MAAM,MAAM;AACV,sBAAgB,WAAW;AAC3B,cAAQ,QAAQ,MAAM;AACtB,wBAAkB;AAAA,IACpB;AAAA,IACA,CAAC,iBAAiB;AAAA,EACpB;AAKA,QAAM,cAAcD;AAAA,IAClB,CAAC,IAAY,SAAe;AAC1B,YAAM,aAAa,gBAAgB;AACnC,WAAK,OACF,WAAW,aAAa;AAAA,QACvB,UAAU,KAAK,QAAQ;AAAA,QACvB,aAAa,KAAK,QAAQ;AAAA,QAC1B,MAAM;AAAA,QACN,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,MAClD,CAAC,EACA,KAAK,CAAC,UAAU;AACf,YAAI,gBAAgB,YAAY,WAAY;AAI5C,gBAAQ,QAAQ,OAAO,EAAE;AACzB;AAAA,UAAe,CAAC,YACd,QAAQ;AAAA,YAAI,CAAC,eACX,WAAW,OAAO,KACd;AAAA,cACE,GAAG;AAAA,cACH,QAAQ;AAAA,cACR,MAAM;AAAA,cACN,MAAM,MAAM;AAAA,cACZ,aAAa,MAAM;AAAA,cACnB,WAAW,MAAM;AAAA,cACjB,WAAW;AAAA,cACX,OAAO;AAAA,cACP,YAAY;AAAA,YACd,IACA;AAAA,UACN;AAAA,QACF;AAAA,MACF,CAAC,EACA,MAAM,CAAC,UAAmB;AACzB,YAAI,gBAAgB,YAAY,WAAY;AAC5C;AAAA,UAAe,CAAC,YACd,QAAQ;AAAA,YAAI,CAAC,eACX,WAAW,OAAO,KACd;AAAA,cACE,GAAG;AAAA,cACH,QAAQ;AAAA,cACR,WAAW,+BAA+B,KAAK;AAAA,cAC/C,OAAO,YAAY,KAAK;AAAA,cACxB,YAAY;AAAA,YACd,IACA;AAAA,UACN;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACL;AAAA,IACA,CAAC,QAAQ,aAAa,QAAQ,OAAO,WAAW;AAAA,EAClD;AAEA,QAAM,WAAWA;AAAA,IACf,CAAC,UAA0B;AACzB,iBAAW,QAAQ,OAAO;AACxB,cAAM,KAAK,mBAAmB;AAC9B,gBAAQ,QAAQ,IAAI,IAAI,IAAI;AAC5B,cAAM,aAAa,QAAQ,IAAI,IAAI,IAAI,gBAAgB,IAAI,IAAI;AAC/D,YAAI,WAAY,aAAY,QAAQ,IAAI,IAAI,UAAU;AACtD,uBAAe,CAAC,YAAY;AAAA,UAC1B,GAAG;AAAA,UACH;AAAA,YACE;AAAA,YACA,MAAM,KAAK,QAAQ;AAAA,YACnB,aAAa,KAAK,QAAQ;AAAA,YAC1B,WAAW,KAAK;AAAA,YAChB,QAAQ;AAAA,YACR,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,UACrC;AAAA,QACF,CAAC;AACD,oBAAY,IAAI,IAAI;AAAA,MACtB;AAAA,IACF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,QAAQA;AAAA,IACZ,CAAC,OAAe;AACd,YAAM,OAAO,QAAQ,QAAQ,IAAI,EAAE;AACnC,UAAI,CAAC,MAAM;AACT;AAAA,MACF;AACA;AAAA,QAAe,CAAC,YACd,QAAQ;AAAA,UAAI,CAAC,eACX,WAAW,OAAO,KACd;AAAA,YACE,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,WAAW;AAAA,YACX,OAAO;AAAA,YACP,YAAY;AAAA,UACd,IACA;AAAA,QACN;AAAA,MACF;AACA,kBAAY,IAAI,IAAI;AAAA,IACtB;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,eAAeA;AAAA,IACnB,CAAC,UAAkD;AACjD,YAAM,iBAAiB,MAAM,eAAe;AAC5C,UAAI,CAAC,gBAAgB;AACnB;AAAA,MACF;AACA,YAAM,QAAQ,CAAC,GAAG,cAAc,EAAE,OAAO,WAAW;AACpD,UAAI,MAAM,SAAS,GAAG;AACpB,iBAAS,KAAK;AAAA,MAChB;AAAA,IACF;AAAA,IACA,CAAC,UAAU,WAAW;AAAA,EACxB;AAEA,QAAM,oBAAoBA;AAAA,IACxB,CAAC,UAA+B;AAC9B,YAAM,WAAW,oBAAI,IAAuB;AAC5C,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,WAAW,WAAW,KAAK,gBAAgB,aAAa;AAC/D,mBAAS,IAAI,KAAK,IAAI,IAAI;AAAA,QAC5B;AAAA,MACF;AACA,qBAAe,CAAC,YAAY;AAC1B,cAAM,aAAa,QAAQ,OAAO,CAAC,eAAe,WAAW,WAAW,OAAO;AAC/E,cAAM,gBAAgB,IAAI;AAAA,UACxB,QAAQ;AAAA,YAAQ,CAAC,eACf,WAAW,WAAW,WAAW,WAAW,OACvC,CAAC,CAAC,WAAW,KAAK,IAAI,UAAU,CAAC,IAClC,CAAC;AAAA,UACP;AAAA,QACF;AACA,cAAM,WAAW,CAAC,GAAG,SAAS,OAAO,CAAC,EAAE,IAAI,CAAC,SAAyB;AACpE,gBAAM,WAAW,cAAc,IAAI,KAAK,EAAE;AAC1C,iBAAO,WACH;AAAA,YACE,GAAG;AAAA,YACH,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB,WAAW,KAAK;AAAA,YAChB,QAAQ;AAAA,YACR;AAAA,YACA,WAAW;AAAA,YACX,OAAO;AAAA,YACP,YAAY;AAAA,UACd,IACA;AAAA,YACE,IAAI,YAAY,KAAK,EAAE;AAAA,YACvB,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB,WAAW,KAAK;AAAA,YAChB,QAAQ;AAAA,YACR;AAAA;AAAA;AAAA,UAGF;AAAA,QACN,CAAC;AAID,eAAO,CAAC,GAAG,YAAY,GAAG,QAAQ;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,cAAcA;AAAA,IAClB,OAAO,IAAY,WAAsD;AACvE,YAAM,aAAa,gBAAgB;AACnC,YAAM,aAAa,eAAe,QAAQ,KAAK,CAAC,cAAc,UAAU,OAAO,EAAE;AACjF,YAAM,oBAAoB,OAAO;AACjC,UACE,CAAC,cACD,WAAW,WAAW,WACtB,CAAC,WAAW,QACZ,CAAC,WAAW,YAAY,WAAW,QAAQ,KAC3C,OAAO,sBAAsB,cAC7B,QAAQ,SACR;AACA,eAAO;AAAA,MACT;AACA,YAAM,SAAS,WAAW,KAAK;AAC/B,YAAM,SAAS,MAAM,kBAAkB,KAAK,QAAQ,aAAa,QAAQ,EAAE,OAAO,CAAC;AACnF,UAAI,gBAAgB,YAAY,cAAc,QAAQ,QAAS,QAAO;AACtE,YAAM,UAAU,eAAe,QAAQ,KAAK,CAAC,cAAc,UAAU,OAAO,EAAE;AAC9E,UAAI,SAAS,WAAW,WAAW,QAAQ,MAAM,OAAO,OAAQ,QAAO;AACvE,aAAO,OAAO;AAAA,IAChB;AAAA,IACA,CAAC,QAAQ,WAAW;AAAA,EACtB;AAEA,QAAM,SAASA;AAAA,IACb,CAAC,OAAe;AACd,cAAQ,QAAQ,OAAO,EAAE;AACzB,oBAAc,EAAE;AAChB,qBAAe,CAAC,YAAY,QAAQ,OAAO,CAAC,eAAe,WAAW,OAAO,EAAE,CAAC;AAAA,IAClF;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,mBAAmBA,aAAY,CAAC,YAA8B;AAClE,UAAM,WAAW,IAAI,IAAI,OAAO;AAChC,QAAI,SAAS,SAAS,EAAG;AACzB;AAAA,MAAe,CAAC,YACd,QAAQ,OAAO,CAAC,eAAe;AAC7B,eAAO,EACL,WAAW,WAAW,WACtB,WAAW,SAAS,UACpB,SAAS,IAAI,WAAW,KAAK,EAAE;AAAA,MAEnC,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQA,aAAY,MAAM;AAC9B,YAAQ,QAAQ,MAAM;AACtB,sBAAkB;AAClB,mBAAe,CAAC,CAAC;AAAA,EACnB,GAAG,CAAC,iBAAiB,CAAC;AAEtB,SAAO;AAAA,IACL;AAAA,IACA,gBAAgB,YAAY;AAAA,MAAQ,CAAC,eACnC,WAAW,WAAW,WAAW,WAAW,OACxC,CAAC,EAAE,MAAM,QAAQ,QAAQ,WAAW,KAAK,GAAG,CAAC,IAC7C,CAAC;AAAA,IACP;AAAA,IACA,WAAW,YAAY,KAAK,CAAC,eAAe,WAAW,WAAW,WAAW;AAAA,IAC7E,eAAe,YAAY,KAAK,CAAC,eAAe,WAAW,WAAW,OAAO;AAAA,IAC7E;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,OAAO,OAAO,0BAA0B,aAAa,EAAE,YAAY,IAAI,CAAC;AAAA,IAC5E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACncA,SAAS,eAAAE,cAAa,mBAAAC,kBAAiB,UAAAC,eAAc;AAyB9C,SAAS,kBACd,WACA,UAAoC,CAAC,GACZ;AACzB,QAAM,EAAE,QAAQ,YAAY,IAAI,mBAAmB,OAAO;AAC1D,QAAM,oBAAoB,GAAG,WAAW,KAAS,aAAa,EAAE;AAChE,QAAM,kBAAkBC,QAId,IAAI;AACd,EAAAC,iBAAgB,MAAM;AACpB,QAAI,gBAAgB,SAAS,cAAc,mBAAmB;AAC5D,sBAAgB,UAAU;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,iBAAiB,CAAC;AACtB,QAAM;AAAA,IACJ,KAAK;AAAA,IACL,UAAU;AAAA,IACV,eAAe;AAAA,IACf,oBAAoB;AAAA,EACtB,IAAI,kBAAkB,iBAAiB;AACvC,QAAM;AAAA,IACJ,KAAK;AAAA,IACL,UAAU;AAAA,IACV,eAAe;AAAA,IACf,oBAAoB;AAAA,EACtB,IAAI,kBAAkB,iBAAiB;AAEvC,QAAM,QAAQC;AAAA,IACZ,OAAO,WAA4D;AACjE,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,aAAO,MAAM;AAAA,QAAW,MACtB,OAAO,aAAa,aAAa,WAAW,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC,CAAC;AAAA,MACpF;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,UAAU;AAAA,EAC7C;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,WAA4D;AACjE,UAAI,CAAC,UAAW,QAAO;AACvB,aAAO,MAAM;AAAA,QAAW,MACtB,OAAO,cAAc,aAAa,WAAW,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,UAAU;AAAA,EAC7C;AAEA,QAAM,SAASA;AAAA,IACb,OACE,YACA,UACA,YACiC;AACjC,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,YAAM,cAAc,KAAK,UAAU,CAAC,YAAY,UAAU,WAAW,IAAI,CAAC;AAC1E,UAAI,gBAAgB,SAAS,gBAAgB,aAAa;AACxD,wBAAgB,UAAU;AAAA,UACxB,WAAW;AAAA,UACX;AAAA,UACA,eAAe,OAAO,WAAW;AAAA,QACnC;AAAA,MACF;AACA,YAAM,gBAAgB,gBAAgB,QAAQ;AAC9C,YAAM,WAAW,MAAM;AAAA,QAAY,MACjC,OAAO,qBAAqB,aAAa,WAAW;AAAA,UAClD;AAAA,UACA;AAAA,UACA,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,UAC3C;AAAA,QACF,CAAC;AAAA,MACH;AACA,UACE,aAAa,QACb,gBAAgB,SAAS,cAAc,qBACvC,gBAAgB,QAAQ,kBAAkB,eAC1C;AACA,wBAAgB,UAAU;AAAA,MAC5B;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,mBAAmB,QAAQ,aAAa,WAAW,WAAW;AAAA,EACjE;AAEA,QAAM,UAAUA;AAAA,IACd,OAAO,YAAoB,YAAqB,MAAM,OAAO,YAAY,WAAW,OAAO;AAAA,IAC3F,CAAC,MAAM;AAAA,EACT;AACA,QAAM,SAASA;AAAA,IACb,OAAO,YAAoB,YAAqB,MAAM,OAAO,YAAY,UAAU,OAAO;AAAA,IAC1F,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,aAAaA,aAAY,MAAM;AACnC,sBAAkB;AAClB,uBAAmB;AAAA,EACrB,GAAG,CAAC,mBAAmB,kBAAkB,CAAC;AAE1C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC5IA;AAAA,EACE;AAAA,OAGK;AAmCA,SAAS,4BAA4B,SAAqC;AAC/E,QAAM,YACJ,WAAW,OAAO,YAAY,WACzB,QAAoC,YACrC;AACN,MAAI,CAAC,MAAM,QAAQ,SAAS,GAAG;AAC7B,WAAO,CAAC;AAAA,EACV;AACA,SAAO,UAAU,IAAI,CAAC,UAAU,UAAU;AACxC,UAAM,MAAO,YAAY,OAAO,aAAa,WAAW,WAAW,CAAC;AAIpE,UAAM,UACJ,IAAI,WAAW,OAAO,IAAI,YAAY,WACjC,IAAI,UACL,CAAC;AACP,UAAM,UAAU,yBAAyB,IAAI,OAAO;AACpD,WAAO;AAAA;AAAA;AAAA,MAGL,IAAI,OAAO,QAAQ,UAAU,QAAQ,MAAM,IAAI,MAAM,IAAI,UAAU,IAAI,QAAQ,KAAK;AAAA,MACpF,MAAM,OAAO,IAAI,QAAQ,IAAI,YAAY,QAAQ,QAAQ,UAAU;AAAA,MACnE,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,WAAW,IAAI,aAAa,QAAQ;AAAA,MACpC,KAAK;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAGO,SAAS,wBAAwB,QAA2C;AACjF,MAAI,UAA6B,CAAC;AAClC,MAAI,eAA8B;AAClC,aAAW,SAAS,QAAQ;AAC1B,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,0BAA0B;AAC7B,kBAAU,4BAA4B,MAAM,OAAO;AACnD,uBAAe,MAAM,UAAU;AAC/B;AAAA,MACF;AAAA,MACA,KAAK,yBAAyB;AAC5B,cAAM,UACJ,MAAM,WAAW,OAAO,MAAM,YAAY,WACrC,MAAM,UACP,CAAC;AACP,YAAI,OAAO,QAAQ,eAAe,UAAU;AAC1C,oBAAU,QAAQ,OAAO,CAAC,aAAa,SAAS,OAAO,QAAQ,UAAU;AAAA,QAC3E;AACA;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,kBAAkB;AAGrB,YAAI,iBAAiB,QAAQ,MAAM,UAAU,QAAQ,MAAM,WAAW,cAAc;AAClF,oBAAU,CAAC;AACX,yBAAe;AAAA,QACjB;AACA;AAAA,MACF;AAAA,MACA;AACE;AAAA,IACJ;AAAA,EACF;AACA,SAAO;AACT;;;ACrGO,SAAS,qBACd,OACA,OACA,UAOgB;AAChB,QAAM,SAAS,IAAI;AAAA,IACjB,MAAM,MACH,OAAO,CAAC,SAAS,KAAK,SAAS,aAAa,OAAO,EACnD,IAAI,CAAC,SAAS,KAAK,cAAc;AAAA,EACtC;AACA,QAAM,UAAU,SAAS,sBAAsB,CAAC;AAChD,QAAM,eAAe,IAAI;AAAA,IACvB,QACG;AAAA,MACC,CAAC,YACC,QAAQ,gBAAgB,WACxB,EACE,QAAQ,UACR,QAAQ,uBAAuB,QAC/B,MAAM,YACN,MAAM,SAAS,WAAW,QAAQ,uBAClC,CAAC,MAAM,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,QAAQ,MAAM;AAAA,IAE5D,EACC,IAAI,CAAC,YAAY,gBAAgB,QAAQ,aAAa,EAAE;AAAA,EAC7D;AACA,QAAM,UAAU,MAAM;AAAA,IACpB,CAAC,SACC,KAAK,SAAS,kBACb,CAAC,OAAO,IAAI,KAAK,EAAE,KAAK,CAAC,aAAa,IAAI,KAAK,qBAAqB,EAAE;AAAA,EAC3E;AACA,QAAM,OAAO,IAAI;AAAA,IACf,QAAQ,QAAQ,CAAC,SAAU,KAAK,SAAS,iBAAiB,CAAC,KAAK,iBAAiB,IAAI,CAAC,CAAE;AAAA,EAC1F;AACA,QAAM,aAAgC,QACnC;AAAA,IACC,CAAC,aACE,QAAQ,gBAAgB,UAAU,QAAQ,UAAU,aACrD,CAAC,KAAK,IAAI,gBAAgB,QAAQ,aAAa,EAAE,KACjD,CAAC,MAAM,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,QAAQ,MAAM;AAAA,EAC1D,EACC,IAAI,CAAC,aAAa;AAAA,IACjB,MAAM;AAAA,IACN,IAAI,cAAc,QAAQ,aAAa;AAAA,IACvC,mBAAmB,gBAAgB,QAAQ,aAAa;AAAA,IACxD,MAAM,QAAQ;AAAA,IACd,aAAa,QAAQ,YAAY,IAAI,CAAC,YAAY,aAAa,EAAE,GAAG,YAAY,QAAQ,EAAE;AAAA,IAC1F,WAAW,QAAQ;AAAA,IACnB,OAAO,CAAC;AAAA,IACR,YAAY,QAAQ;AAAA,IACpB,UAAU;AAAA,MACR,OAAO,QAAQ;AAAA,MACf,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,MAChD,GAAI,QAAQ,UAAU,WAClB;AAAA,QACE,GAAI,QAAQ,cAAc,SAAS,SAAS,yBACxC,EAAE,SAAS,MAAM,SAAS,yBAAyB,QAAQ,aAAa,EAAE,IAC1E,CAAC;AAAA,QACL,GAAI,QAAQ,cAAc,SAAS,SAAS,2BACxC,EAAE,QAAQ,MAAM,SAAS,2BAA2B,QAAQ,aAAa,EAAE,IAC3E,CAAC;AAAA,QACL,UAAU,MAAM,SAAS,0BAA0B,QAAQ,aAAa;AAAA,MAC1E,IACA,CAAC;AAAA,IACP;AAAA,EACF,EAAE;AACJ,QAAM,MAAM,IAAI,IAAI,QAAQ,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAClD,QAAM,UAA6B,MAAM,kBAAkB,CAAC,GACzD,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI,MAAM,cAAc,CAAC,EAChD,IAAI,CAAC,WAAW;AAAA,IACf,MAAM;AAAA,IACN,IAAI,MAAM;AAAA,IACV,MAAM,MAAM;AAAA,IACZ,aAAa,MAAM;AAAA,IACnB,WAAW,MAAM;AAAA,IACjB,OAAO,MAAM;AAAA,IACb,YAAY,MAAM;AAAA,IAClB,UAAU,EAAE,OAAO,MAAM,MAAM;AAAA,EACjC,EAAE;AACJ,SAAO,CAAC,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM;AAC9C;","names":["useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useCallback","readGeneration","useEffect","useMemo","useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useEffect","useCallback","useMemo","useCallback","useEffect","useRef","useState","useCallback","useState","useRef","useEffect","now","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useLayoutEffect","useRef","useRef","useLayoutEffect","useCallback"]}