botmux 3.2.0 → 3.2.1

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 (169) hide show
  1. package/README.en.md +1 -0
  2. package/README.md +1 -0
  3. package/dist/adapters/cli/codex.d.ts.map +1 -1
  4. package/dist/adapters/cli/codex.js +13 -1
  5. package/dist/adapters/cli/codex.js.map +1 -1
  6. package/dist/adapters/cli/traex.d.ts.map +1 -1
  7. package/dist/adapters/cli/traex.js +11 -1
  8. package/dist/adapters/cli/traex.js.map +1 -1
  9. package/dist/adapters/cli/types.d.ts +6 -0
  10. package/dist/adapters/cli/types.d.ts.map +1 -1
  11. package/dist/bot-registry.d.ts +7 -0
  12. package/dist/bot-registry.d.ts.map +1 -1
  13. package/dist/bot-registry.js +1 -0
  14. package/dist/bot-registry.js.map +1 -1
  15. package/dist/cli/daemon-lifecycle-env.d.ts +11 -0
  16. package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -0
  17. package/dist/cli/daemon-lifecycle-env.js +25 -0
  18. package/dist/cli/daemon-lifecycle-env.js.map +1 -0
  19. package/dist/cli.d.ts.map +1 -1
  20. package/dist/cli.js +11 -4
  21. package/dist/cli.js.map +1 -1
  22. package/dist/codex-rpc-engine.d.ts +110 -0
  23. package/dist/codex-rpc-engine.d.ts.map +1 -0
  24. package/dist/codex-rpc-engine.js +496 -0
  25. package/dist/codex-rpc-engine.js.map +1 -0
  26. package/dist/codex-rpc-lifecycle.d.ts +157 -0
  27. package/dist/codex-rpc-lifecycle.d.ts.map +1 -0
  28. package/dist/codex-rpc-lifecycle.js +210 -0
  29. package/dist/codex-rpc-lifecycle.js.map +1 -0
  30. package/dist/config.d.ts +1 -0
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/config.js +14 -2
  33. package/dist/config.js.map +1 -1
  34. package/dist/core/attachment-path.d.ts +3 -0
  35. package/dist/core/attachment-path.d.ts.map +1 -0
  36. package/dist/core/attachment-path.js +8 -0
  37. package/dist/core/attachment-path.js.map +1 -0
  38. package/dist/core/command-handler.d.ts.map +1 -1
  39. package/dist/core/command-handler.js +6 -1
  40. package/dist/core/command-handler.js.map +1 -1
  41. package/dist/core/dashboard-images.d.ts +29 -0
  42. package/dist/core/dashboard-images.d.ts.map +1 -0
  43. package/dist/core/dashboard-images.js +113 -0
  44. package/dist/core/dashboard-images.js.map +1 -0
  45. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  46. package/dist/core/dashboard-ipc-server.js +13 -1
  47. package/dist/core/dashboard-ipc-server.js.map +1 -1
  48. package/dist/core/github-auth.d.ts +5 -0
  49. package/dist/core/github-auth.d.ts.map +1 -1
  50. package/dist/core/github-auth.js +38 -0
  51. package/dist/core/github-auth.js.map +1 -1
  52. package/dist/core/maintenance.d.ts +1 -0
  53. package/dist/core/maintenance.d.ts.map +1 -1
  54. package/dist/core/maintenance.js +9 -1
  55. package/dist/core/maintenance.js.map +1 -1
  56. package/dist/core/session-create.d.ts +10 -0
  57. package/dist/core/session-create.d.ts.map +1 -1
  58. package/dist/core/session-create.js +21 -0
  59. package/dist/core/session-create.js.map +1 -1
  60. package/dist/core/session-manager.d.ts +4 -1
  61. package/dist/core/session-manager.d.ts.map +1 -1
  62. package/dist/core/session-manager.js +25 -13
  63. package/dist/core/session-manager.js.map +1 -1
  64. package/dist/core/trigger-session.d.ts +3 -0
  65. package/dist/core/trigger-session.d.ts.map +1 -1
  66. package/dist/core/trigger-session.js +17 -3
  67. package/dist/core/trigger-session.js.map +1 -1
  68. package/dist/core/worker-pool.d.ts.map +1 -1
  69. package/dist/core/worker-pool.js +2 -0
  70. package/dist/core/worker-pool.js.map +1 -1
  71. package/dist/daemon.d.ts.map +1 -1
  72. package/dist/daemon.js +19 -3
  73. package/dist/daemon.js.map +1 -1
  74. package/dist/dashboard/connector-api.d.ts.map +1 -1
  75. package/dist/dashboard/connector-api.js +19 -0
  76. package/dist/dashboard/connector-api.js.map +1 -1
  77. package/dist/dashboard/settings-write-applier.d.ts +2 -1
  78. package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
  79. package/dist/dashboard/settings-write-applier.js +6 -0
  80. package/dist/dashboard/settings-write-applier.js.map +1 -1
  81. package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
  82. package/dist/dashboard/web/connectors-page.js +23 -2
  83. package/dist/dashboard/web/connectors-page.js.map +1 -1
  84. package/dist/dashboard/web/create-session-composer.d.ts +35 -0
  85. package/dist/dashboard/web/create-session-composer.d.ts.map +1 -0
  86. package/dist/dashboard/web/create-session-composer.js +70 -0
  87. package/dist/dashboard/web/create-session-composer.js.map +1 -0
  88. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  89. package/dist/dashboard/web/i18n.js +65 -5
  90. package/dist/dashboard/web/i18n.js.map +1 -1
  91. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  92. package/dist/dashboard/web/sessions-page.js +147 -1
  93. package/dist/dashboard/web/sessions-page.js.map +1 -1
  94. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  95. package/dist/dashboard/web/settings-page.js +2 -1
  96. package/dist/dashboard/web/settings-page.js.map +1 -1
  97. package/dist/dashboard/web/skills-page.d.ts.map +1 -1
  98. package/dist/dashboard/web/skills-page.js +5 -2
  99. package/dist/dashboard/web/skills-page.js.map +1 -1
  100. package/dist/dashboard/webhook-routes.d.ts +4 -0
  101. package/dist/dashboard/webhook-routes.d.ts.map +1 -1
  102. package/dist/dashboard/webhook-routes.js +19 -0
  103. package/dist/dashboard/webhook-routes.js.map +1 -1
  104. package/dist/dashboard-web/app.js +1 -1
  105. package/dist/dashboard-web/chunks/{bot-defaults-page-4PM4T6QQ.js → bot-defaults-page-O37SAQD5.js} +1 -1
  106. package/dist/dashboard-web/chunks/{chunk-RXVA6XW3.js → chunk-6QHMLMIM.js} +6 -6
  107. package/dist/dashboard-web/chunks/{chunk-IKCZ677K.js → chunk-B42PCL5P.js} +1 -1
  108. package/dist/dashboard-web/chunks/{chunk-3PMN55Z6.js → chunk-FYALHCPG.js} +1 -1
  109. package/dist/dashboard-web/chunks/{chunk-AIDN2WZB.js → chunk-O2DPQL7C.js} +1 -1
  110. package/dist/dashboard-web/chunks/connectors-page-DZBQ42MH.js +1 -0
  111. package/dist/dashboard-web/chunks/{groups-page-TAU2UIVS.js → groups-page-3IEGRZKQ.js} +1 -1
  112. package/dist/dashboard-web/chunks/{insights-page-PJ2XVM6T.js → insights-page-X3ADRON3.js} +1 -1
  113. package/dist/dashboard-web/chunks/{monitor-room-D6445HJO.js → monitor-room-IV36RGQY.js} +1 -1
  114. package/dist/dashboard-web/chunks/{monitoring-page-GUHMCKSO.js → monitoring-page-ADFKVON4.js} +1 -1
  115. package/dist/dashboard-web/chunks/{office-page-6K6U2MS5.js → office-page-CALAOWNS.js} +1 -1
  116. package/dist/dashboard-web/chunks/{overview-page-USDYU7U5.js → overview-page-SLMGLK3M.js} +1 -1
  117. package/dist/dashboard-web/chunks/{roles-page-O4OUA7ZH.js → roles-page-L7JJ4FFV.js} +1 -1
  118. package/dist/dashboard-web/chunks/{schedules-page-LNIBXJSZ.js → schedules-page-Z3672POL.js} +1 -1
  119. package/dist/dashboard-web/chunks/sessions-page-OKJ5YWUZ.js +3 -0
  120. package/dist/dashboard-web/chunks/settings-page-P6MI2ZUE.js +2 -0
  121. package/dist/dashboard-web/chunks/{skills-page-M5KYNXBA.js → skills-page-FT7BVZ6X.js} +4 -4
  122. package/dist/dashboard-web/chunks/{team-federation-page-GT7UFQMN.js → team-federation-page-DEYCPUFB.js} +1 -1
  123. package/dist/dashboard-web/chunks/{v3-page-UYZIRJ2C.js → v3-page-4IOWREZG.js} +1 -1
  124. package/dist/dashboard-web/chunks/{whiteboards-page-WAR77DQE.js → whiteboards-page-2VMBETZH.js} +1 -1
  125. package/dist/dashboard-web/style.css +191 -0
  126. package/dist/dashboard.js +33 -6
  127. package/dist/dashboard.js.map +1 -1
  128. package/dist/global-config.d.ts +7 -0
  129. package/dist/global-config.d.ts.map +1 -1
  130. package/dist/global-config.js +2 -0
  131. package/dist/global-config.js.map +1 -1
  132. package/dist/im/lark/ask-card.d.ts.map +1 -1
  133. package/dist/im/lark/ask-card.js +52 -4
  134. package/dist/im/lark/ask-card.js.map +1 -1
  135. package/dist/im/lark/card-handler.d.ts +2 -0
  136. package/dist/im/lark/card-handler.d.ts.map +1 -1
  137. package/dist/im/lark/card-handler.js +19 -2
  138. package/dist/im/lark/card-handler.js.map +1 -1
  139. package/dist/im/lark/event-dispatcher.d.ts +3 -0
  140. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  141. package/dist/im/lark/event-dispatcher.js +706 -693
  142. package/dist/im/lark/event-dispatcher.js.map +1 -1
  143. package/dist/im/lark/grant-pending.d.ts +8 -4
  144. package/dist/im/lark/grant-pending.d.ts.map +1 -1
  145. package/dist/im/lark/grant-pending.js +13 -6
  146. package/dist/im/lark/grant-pending.js.map +1 -1
  147. package/dist/services/connector-store.d.ts +8 -0
  148. package/dist/services/connector-store.d.ts.map +1 -1
  149. package/dist/services/connector-store.js.map +1 -1
  150. package/dist/services/session-store.d.ts +2 -1
  151. package/dist/services/session-store.d.ts.map +1 -1
  152. package/dist/services/session-store.js +60 -2
  153. package/dist/services/session-store.js.map +1 -1
  154. package/dist/services/skill-registry-store.d.ts +16 -0
  155. package/dist/services/skill-registry-store.d.ts.map +1 -1
  156. package/dist/services/skill-registry-store.js +343 -47
  157. package/dist/services/skill-registry-store.js.map +1 -1
  158. package/dist/services/trigger-types.d.ts +5 -0
  159. package/dist/services/trigger-types.d.ts.map +1 -1
  160. package/dist/services/trigger-types.js +12 -0
  161. package/dist/services/trigger-types.js.map +1 -1
  162. package/dist/types.d.ts +13 -2
  163. package/dist/types.d.ts.map +1 -1
  164. package/dist/worker.js +440 -34
  165. package/dist/worker.js.map +1 -1
  166. package/package.json +1 -1
  167. package/dist/dashboard-web/chunks/connectors-page-2MKF4YTN.js +0 -1
  168. package/dist/dashboard-web/chunks/sessions-page-B6U6TCFF.js +0 -3
  169. package/dist/dashboard-web/chunks/settings-page-PXLRFF7I.js +0 -2
@@ -0,0 +1,110 @@
1
+ type LogFn = (msg: string) => void;
2
+ export interface CodexRpcEngineOpts {
3
+ /** Absolute path to the codex-family CLI binary (codex / traex / …). */
4
+ cliBin: string;
5
+ /** Working directory / agent root for the session. */
6
+ cwd: string;
7
+ /** Child env (must carry CODEX_HOME + proxy vars + BOTMUX_SESSION_ID). */
8
+ env: NodeJS.ProcessEnv;
9
+ /** botmux session id — used to name the app-server orphan-cleanup marker so a
10
+ * new incarnation of this session can reap a prior app-server (P0 teardown). */
11
+ sessionId?: string;
12
+ log?: LogFn;
13
+ /** Optional model + reasoning effort forwarded to thread config (P1). */
14
+ model?: string;
15
+ reasoningEffort?: string;
16
+ /** Override the per-request JSON-RPC timeout (default REQUEST_TIMEOUT_MS).
17
+ * Mainly for tests that assert the wedged-app-server recovery path. */
18
+ requestTimeoutMs?: number;
19
+ /** Called once if the app-server dies unexpectedly (not via stop()). The
20
+ * worker uses it to kill the now-orphaned `codex --remote` pane so the normal
21
+ * exit→daemon-refork→resume path re-engages RPC on a fresh app-server (P1). */
22
+ onDead?: () => void;
23
+ }
24
+ export declare class CodexRpcEngine {
25
+ private readonly opts;
26
+ private child?;
27
+ private ws?;
28
+ private nextId;
29
+ private pending;
30
+ private port;
31
+ private threadId?;
32
+ private closed;
33
+ private deadNotified;
34
+ private lastStderr;
35
+ private readonly log;
36
+ constructor(opts: CodexRpcEngineOpts);
37
+ get wsUrl(): string;
38
+ get activeThreadId(): string | undefined;
39
+ get appServerPid(): number | undefined;
40
+ /** Spawn the app-server, connect, and complete the initialize handshake. */
41
+ start(): Promise<void>;
42
+ /** Create a fresh session thread. Its id (== codex rollout session id) is what
43
+ * the TUI resumes and what botmux persists for future resume. */
44
+ startThread(): Promise<string>;
45
+ /** Resume the persisted thread after a botmux reconnect (P0 resume-survival),
46
+ * so RPC mode stays engaged across daemon restarts instead of reverting to
47
+ * the paste path. */
48
+ resumeThread(threadId: string): Promise<string>;
49
+ private threadParams;
50
+ /** Inject one user message as a turn. Resolves when the app-server acks the
51
+ * turn start (fast); the turn itself streams to the attached TUI.
52
+ * `clientUserMessageId` (a stable botmux turn id) is forwarded so codex can
53
+ * CORRELATE the message — NOT relied on for dedupe (the 0.144.1 schema carries
54
+ * it but promises no idempotency). Correctness comes from the caller never
55
+ * auto-resending an accepted turn (P1-1).
56
+ * opts.fatalOnTimeout=false makes a timeout reject only THIS request instead of
57
+ * tearing the engine down — used for the fresh first turn, whose ambiguity is
58
+ * then resolved against rollout persistence (see sendFirstTurn). */
59
+ sendTurn(content: string, clientUserMessageId?: string, opts?: {
60
+ timeoutMs?: number;
61
+ fatalOnTimeout?: boolean;
62
+ }): Promise<void>;
63
+ /** Deliver the FRESH first turn and resolve its outcome as one of THREE states,
64
+ * prioritising exactly-once over never-lost (P1-1). An empty thread can't be
65
+ * resumed by the TUI, so the first turn must persist the rollout before the
66
+ * pane spawns — but a lost/late ack must NOT be blindly re-pasted (that would
67
+ * double-execute, the failure users care about most):
68
+ * - 'accepted' — ack received, OR (ack lost) the rollout already contains
69
+ * THIS turn's user message → engaged, never resend.
70
+ * - 'not-sent' — the turn/start FRAME was never dispatched (ws not open /
71
+ * send threw) → the turn cannot have run → safe paste once.
72
+ * - 'ambiguous' — the frame WAS dispatched but no ack AND no positive rollout
73
+ * evidence (timeout / transport / server / unknown error) →
74
+ * it may have executed → NEVER auto-paste; the caller notifies
75
+ * the user and lets the viewer resume (recovers if it landed).
76
+ * Only "frame not dispatched" is treated as safe; every dispatched-then-failed
77
+ * case is ambiguous, and a timeout is non-fatal so the engine survives to serve
78
+ * the accepted/ambiguous cases. `rolloutProbe` is the ground-truth positive
79
+ * check (matches this turn's user_message in the persisted rollout). */
80
+ sendFirstTurn(content: string, clientUserMessageId: string | undefined, rolloutProbe: (threadId: string) => Promise<boolean>): Promise<'accepted' | 'not-sent' | 'ambiguous'>;
81
+ stop(): void;
82
+ private markerPath;
83
+ /** Verify a pid is actually OUR app-server before signalling it — the marker
84
+ * can outlive a SIGKILLed worker and its pid may be REUSED by an unrelated
85
+ * process (daemon runs as root → mis-kill would be severe). Match the process
86
+ * argv against `app-server` AND, when recorded, the exact `--listen <url>` a
87
+ * reused pid could not carry (P1-2). */
88
+ private processIsOurAppServer;
89
+ /** Kill an app-server left behind by a prior incarnation of this session
90
+ * (e.g. the worker was SIGKILLed so its exit hooks never ran). Identity-checked
91
+ * so a reused pid is never mis-killed. */
92
+ private reapStaleAppServer;
93
+ private writeMarker;
94
+ /** Remove the marker ONLY if it still names THIS engine's app-server (pid +
95
+ * wsUrl). Prevents an ABA race: a same-session engine B may have already
96
+ * reaped + rewritten the marker with its own pid/url by the time this (old)
97
+ * engine's child exits late — an unconditional delete would orphan B's live
98
+ * app-server (no marker → next incarnation can't reap it). P1-2. */
99
+ private removeMarkerIfOwned;
100
+ private waitReady;
101
+ private connect;
102
+ private request;
103
+ private notify;
104
+ private respond;
105
+ private send;
106
+ private onMessage;
107
+ private failAll;
108
+ }
109
+ export {};
110
+ //# sourceMappingURL=codex-rpc-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-rpc-engine.d.ts","sourceRoot":"","sources":["../src/codex-rpc-engine.ts"],"names":[],"mappings":"AAgCA,KAAK,KAAK,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAwBnC,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB;qFACiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,KAAK,CAAC;IACZ,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;4EACwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;oFAEgF;IAChF,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAwBD,qBAAa,cAAc;IAYb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAXjC,OAAO,CAAC,KAAK,CAAC,CAAe;IAC7B,OAAO,CAAC,EAAE,CAAC,CAAY;IACvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAsH;IACrI,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;gBAEC,IAAI,EAAE,kBAAkB;IAIrD,IAAI,KAAK,IAAI,MAAM,CAA0C;IAC7D,IAAI,cAAc,IAAI,MAAM,GAAG,SAAS,CAA0B;IAClE,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAA4B;IAElE,4EAA4E;IACtE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B5B;sEACkE;IAC5D,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAOpC;;0BAEsB;IAChB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQrD,OAAO,CAAC,YAAY;IAmBpB;;;;;;;;yEAQqE;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,mBAAmB,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAarI;;;;;;;;;;;;;;;;6EAgByE;IACnE,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;IA6BnL,IAAI,IAAI,IAAI;IAoBZ,OAAO,CAAC,UAAU;IAKlB;;;;6CAIyC;IACzC,OAAO,CAAC,qBAAqB;IAY7B;;+CAE2C;IAC3C,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,WAAW;IAQnB;;;;yEAIqE;IACrE,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,SAAS;IAsBjB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,OAAO;IAqCf,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,SAAS;IAsBjB,OAAO,CAAC,OAAO;CAShB"}
@@ -0,0 +1,496 @@
1
+ // Hybrid Codex input engine.
2
+ //
3
+ // Runs one `codex app-server --listen ws://127.0.0.1:<port>` per session (the
4
+ // shared engine) and speaks JSON-RPC to it. The session's tmux pane runs the
5
+ // real `codex --remote ws://... resume <threadId>` TUI, so rendering / web
6
+ // terminal / idle detection are unchanged. User input is delivered via
7
+ // `turn/start` (an acked RPC) instead of a tmux paste — bypassing the terminal
8
+ // entirely, which is where codex drops bracketed pastes during its startup /
9
+ // settings-churn terminal re-init (see codex-0144 investigation).
10
+ //
11
+ // Coordination (verified — raw-WS repro + real `codex --remote` TUI): the
12
+ // app-server BROADCASTS a thread's turn/item events to EVERY connection that has
13
+ // the thread open (engine `thread/start`/`resume` + TUI `resume`), and the real
14
+ // TUI renders events for a turn another connection issued. So the engine owns the
15
+ // thread (`thread/start`, then the first turn — an empty thread has no rollout so
16
+ // the TUI can't resume it, hence the first turn persists the rollout BEFORE the
17
+ // TUI attaches), the TUI `resume`s it, and every engine turn thereafter renders
18
+ // live in the TUI via that broadcast. On a botmux resume (daemon restart /
19
+ // re-fork), the engine `thread/resume`s the persisted thread id AND the pane is
20
+ // respawned as a fresh `--remote resume` against the CURRENT app-server (a new
21
+ // port each incarnation) — reattaching the prior pane would leave it pointed at
22
+ // the now-dead prior app-server (that lifecycle bug, not any non-broadcast, is
23
+ // what froze the Web terminal). See codex-rpc-lifecycle + worker engageCodexRpc.
24
+ import { spawn, execFileSync } from 'node:child_process';
25
+ import { createServer } from 'node:net';
26
+ import { get as httpGet } from 'node:http';
27
+ import { existsSync, readFileSync, writeFileSync, rmSync, mkdirSync } from 'node:fs';
28
+ import { join } from 'node:path';
29
+ import { homedir } from 'node:os';
30
+ import { WebSocket } from 'ws';
31
+ async function findFreePort() {
32
+ return new Promise((resolve, reject) => {
33
+ const srv = createServer();
34
+ srv.once('error', reject);
35
+ srv.listen(0, '127.0.0.1', () => {
36
+ const addr = srv.address();
37
+ const port = addr && typeof addr === 'object' ? addr.port : 0;
38
+ srv.close(() => (port ? resolve(port) : reject(new Error('no free port'))));
39
+ });
40
+ });
41
+ }
42
+ function isAlive(pid) {
43
+ try {
44
+ process.kill(pid, 0);
45
+ return true;
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ }
51
+ /** Kill the whole process group (node wrapper + its native app-server child).
52
+ * The app-server is spawned `detached`, so its pid is the group leader. */
53
+ function killGroup(pid, signal) {
54
+ try {
55
+ process.kill(-pid, signal);
56
+ }
57
+ catch {
58
+ try {
59
+ process.kill(pid, signal);
60
+ }
61
+ catch { /* gone */ }
62
+ }
63
+ }
64
+ /** Server→client requests are auto-answered so codex never blocks on a human;
65
+ * botmux already runs codex with approvals bypassed. Mirrors codex-app-runner. */
66
+ function autoApproval(method) {
67
+ if (method === 'item/permissions/requestApproval')
68
+ return { permissions: {}, scope: 'turn' };
69
+ if (method === 'item/tool/requestUserInput')
70
+ return { answers: {} };
71
+ if (method === 'mcpServer/elicitation/request')
72
+ return { action: 'cancel', content: null, _meta: null };
73
+ if (method === 'item/tool/call')
74
+ return { contentItems: [], success: false };
75
+ if (method === 'execCommandApproval' || method === 'applyPatchApproval')
76
+ return { decision: 'approved_for_session' };
77
+ // commandExecution / fileChange requestApproval + anything else: accept.
78
+ return { decision: 'acceptForSession' };
79
+ }
80
+ const MARKER_DIR = join(homedir(), '.botmux', 'data', 'codex-rpc-app-servers');
81
+ /** Per JSON-RPC request timeout. Without it, a connected-but-wedged app-server
82
+ * (never answers turn/start / initialize / thread/*) would leave the caller
83
+ * awaiting forever — flushPending would stick in isFlushing and silently drop
84
+ * every later message (P1-5). A rejected request unblocks the caller, which
85
+ * fails-closed (engage) or surfaces a resync (sendTurn). Generous because the
86
+ * FIRST turn on a cold app-server pays MCP/model-list startup latency. */
87
+ const REQUEST_TIMEOUT_MS = 60_000;
88
+ export class CodexRpcEngine {
89
+ opts;
90
+ child;
91
+ ws;
92
+ nextId = 1;
93
+ pending = new Map();
94
+ port = 0;
95
+ threadId;
96
+ closed = false;
97
+ deadNotified = false;
98
+ lastStderr = '';
99
+ log;
100
+ constructor(opts) {
101
+ this.opts = opts;
102
+ this.log = opts.log ?? (() => { });
103
+ }
104
+ get wsUrl() { return `ws://127.0.0.1:${this.port}`; }
105
+ get activeThreadId() { return this.threadId; }
106
+ get appServerPid() { return this.child?.pid; }
107
+ /** Spawn the app-server, connect, and complete the initialize handshake. */
108
+ async start() {
109
+ this.reapStaleAppServer();
110
+ this.port = await findFreePort();
111
+ this.child = spawn(this.opts.cliBin, ['app-server', '--listen', `ws://127.0.0.1:${this.port}`], {
112
+ cwd: this.opts.cwd,
113
+ env: this.opts.env,
114
+ stdio: ['ignore', 'ignore', 'pipe'],
115
+ // Own process group so stop()/reap can kill the node wrapper AND its
116
+ // native app-server child in one shot (killGroup → kill(-pid)).
117
+ detached: true,
118
+ });
119
+ this.child.unref(); // don't let the app-server keep the worker's loop alive
120
+ this.child.stderr?.on('data', (c) => {
121
+ this.lastStderr = (this.lastStderr + c.toString('utf8')).slice(-4000);
122
+ });
123
+ this.child.once('error', err => this.failAll(new Error(`codex app-server spawn failed: ${err.message}`)));
124
+ this.child.once('exit', (code, signal) => {
125
+ this.removeMarkerIfOwned(); // child confirmed dead → drop OUR marker only (ABA-safe)
126
+ if (!this.closed)
127
+ this.failAll(new Error(`codex app-server exited (code=${code}, signal=${signal})${this.lastStderr ? `\n${this.lastStderr}` : ''}`));
128
+ });
129
+ this.writeMarker();
130
+ await this.waitReady(15_000);
131
+ await this.connect(8_000);
132
+ await this.request('initialize', {
133
+ clientInfo: { name: 'botmux', version: '0.0.0', title: 'botmux' },
134
+ capabilities: { experimentalApi: true },
135
+ });
136
+ this.notify('initialized');
137
+ }
138
+ /** Create a fresh session thread. Its id (== codex rollout session id) is what
139
+ * the TUI resumes and what botmux persists for future resume. */
140
+ async startThread() {
141
+ const r = await this.request('thread/start', this.threadParams());
142
+ this.threadId = String(r?.thread?.id ?? '');
143
+ if (!this.threadId)
144
+ throw new Error('thread/start returned no thread id');
145
+ return this.threadId;
146
+ }
147
+ /** Resume the persisted thread after a botmux reconnect (P0 resume-survival),
148
+ * so RPC mode stays engaged across daemon restarts instead of reverting to
149
+ * the paste path. */
150
+ async resumeThread(threadId) {
151
+ const params = { ...this.threadParams(), threadId, excludeTurns: true };
152
+ delete params.serviceName; // resume keeps the original thread's identity
153
+ const r = await this.request('thread/resume', params);
154
+ this.threadId = String(r?.thread?.id ?? threadId);
155
+ return this.threadId;
156
+ }
157
+ threadParams() {
158
+ const config = {
159
+ // Forward the full env (incl. BOTMUX_SESSION_ID / BOTMUX_LARK_APP_ID) to
160
+ // shell subprocesses so `botmux send` from within codex finds its bot.
161
+ shell_environment_policy: { inherit: 'all', ignore_default_excludes: true },
162
+ };
163
+ if (this.opts.model)
164
+ config.model = this.opts.model;
165
+ if (this.opts.reasoningEffort)
166
+ config.model_reasoning_effort = this.opts.reasoningEffort;
167
+ return {
168
+ cwd: this.opts.cwd,
169
+ approvalPolicy: 'never',
170
+ sandbox: 'danger-full-access',
171
+ serviceName: 'botmux',
172
+ ephemeral: false,
173
+ persistExtendedHistory: true,
174
+ config,
175
+ };
176
+ }
177
+ /** Inject one user message as a turn. Resolves when the app-server acks the
178
+ * turn start (fast); the turn itself streams to the attached TUI.
179
+ * `clientUserMessageId` (a stable botmux turn id) is forwarded so codex can
180
+ * CORRELATE the message — NOT relied on for dedupe (the 0.144.1 schema carries
181
+ * it but promises no idempotency). Correctness comes from the caller never
182
+ * auto-resending an accepted turn (P1-1).
183
+ * opts.fatalOnTimeout=false makes a timeout reject only THIS request instead of
184
+ * tearing the engine down — used for the fresh first turn, whose ambiguity is
185
+ * then resolved against rollout persistence (see sendFirstTurn). */
186
+ async sendTurn(content, clientUserMessageId, opts) {
187
+ if (!this.threadId)
188
+ throw new Error('sendTurn before startThread/resumeThread');
189
+ const params = {
190
+ threadId: this.threadId,
191
+ input: [{ type: 'text', text: content, text_elements: [] }],
192
+ cwd: this.opts.cwd,
193
+ approvalPolicy: 'never',
194
+ sandboxPolicy: { type: 'dangerFullAccess' },
195
+ };
196
+ if (clientUserMessageId)
197
+ params.clientUserMessageId = clientUserMessageId;
198
+ await this.request('turn/start', params, opts);
199
+ }
200
+ /** Deliver the FRESH first turn and resolve its outcome as one of THREE states,
201
+ * prioritising exactly-once over never-lost (P1-1). An empty thread can't be
202
+ * resumed by the TUI, so the first turn must persist the rollout before the
203
+ * pane spawns — but a lost/late ack must NOT be blindly re-pasted (that would
204
+ * double-execute, the failure users care about most):
205
+ * - 'accepted' — ack received, OR (ack lost) the rollout already contains
206
+ * THIS turn's user message → engaged, never resend.
207
+ * - 'not-sent' — the turn/start FRAME was never dispatched (ws not open /
208
+ * send threw) → the turn cannot have run → safe paste once.
209
+ * - 'ambiguous' — the frame WAS dispatched but no ack AND no positive rollout
210
+ * evidence (timeout / transport / server / unknown error) →
211
+ * it may have executed → NEVER auto-paste; the caller notifies
212
+ * the user and lets the viewer resume (recovers if it landed).
213
+ * Only "frame not dispatched" is treated as safe; every dispatched-then-failed
214
+ * case is ambiguous, and a timeout is non-fatal so the engine survives to serve
215
+ * the accepted/ambiguous cases. `rolloutProbe` is the ground-truth positive
216
+ * check (matches this turn's user_message in the persisted rollout). */
217
+ async sendFirstTurn(content, clientUserMessageId, rolloutProbe) {
218
+ const threadId = this.threadId;
219
+ if (!threadId)
220
+ throw new Error('sendFirstTurn before startThread');
221
+ let dispatched = false;
222
+ const params = {
223
+ threadId,
224
+ input: [{ type: 'text', text: content, text_elements: [] }],
225
+ cwd: this.opts.cwd,
226
+ approvalPolicy: 'never',
227
+ sandboxPolicy: { type: 'dangerFullAccess' },
228
+ };
229
+ if (clientUserMessageId)
230
+ params.clientUserMessageId = clientUserMessageId;
231
+ try {
232
+ await this.request('turn/start', params, { timeoutMs: this.opts.requestTimeoutMs ?? 15_000, fatalOnTimeout: false }, () => { dispatched = true; });
233
+ return 'accepted'; // ack received
234
+ }
235
+ catch (err) {
236
+ if (!dispatched) {
237
+ this.log(`[codex-rpc] first turn/start not dispatched (${err.message}); safe to paste`);
238
+ return 'not-sent';
239
+ }
240
+ // Dispatched but no ack — the ONLY safe resolution is positive rollout
241
+ // evidence; absence is NOT proof it didn't run (it may persist >window or be
242
+ // queued server-side), so no-evidence stays ambiguous.
243
+ this.log(`[codex-rpc] first turn ack lost after dispatch (${err.message}); checking rollout for positive evidence`);
244
+ const landed = await rolloutProbe(threadId);
245
+ return landed ? 'accepted' : 'ambiguous';
246
+ }
247
+ }
248
+ stop() {
249
+ this.closed = true;
250
+ try {
251
+ this.ws?.close();
252
+ }
253
+ catch { /* already gone */ }
254
+ const pid = this.child?.pid;
255
+ if (pid) {
256
+ // Bounded SIGTERM → SIGKILL: don't leave a stubborn child as an untracked
257
+ // orphan. The marker is removed by the child 'exit' handler (confirmed
258
+ // dead), NOT here — if the child ignores SIGTERM and this worker then dies,
259
+ // the surviving marker lets the next incarnation reap it (P1-2).
260
+ try {
261
+ killGroup(pid, 'SIGTERM');
262
+ }
263
+ catch { /* already gone */ }
264
+ const t = setTimeout(() => { if (isAlive(pid)) {
265
+ try {
266
+ killGroup(pid, 'SIGKILL');
267
+ }
268
+ catch { /* */ }
269
+ } }, 2000);
270
+ t.unref?.();
271
+ }
272
+ else {
273
+ this.removeMarkerIfOwned();
274
+ }
275
+ this.failAll(new Error('engine stopped'));
276
+ }
277
+ // ---- app-server orphan marker (P0 teardown) ------------------------------
278
+ markerPath() {
279
+ if (!this.opts.sessionId)
280
+ return undefined;
281
+ return join(MARKER_DIR, `${this.opts.sessionId}.pid`);
282
+ }
283
+ /** Verify a pid is actually OUR app-server before signalling it — the marker
284
+ * can outlive a SIGKILLed worker and its pid may be REUSED by an unrelated
285
+ * process (daemon runs as root → mis-kill would be severe). Match the process
286
+ * argv against `app-server` AND, when recorded, the exact `--listen <url>` a
287
+ * reused pid could not carry (P1-2). */
288
+ processIsOurAppServer(pid, markedUrl) {
289
+ let argv = '';
290
+ try {
291
+ argv = readFileSync(`/proc/${pid}/cmdline`, 'utf8').replace(/\0/g, ' ');
292
+ }
293
+ catch {
294
+ try {
295
+ argv = execFileSync('ps', ['-o', 'args=', '-p', String(pid)], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
296
+ }
297
+ catch {
298
+ return false;
299
+ }
300
+ }
301
+ if (!/\bapp-server\b/.test(argv))
302
+ return false;
303
+ if (markedUrl && !argv.includes(markedUrl))
304
+ return false;
305
+ return true;
306
+ }
307
+ /** Kill an app-server left behind by a prior incarnation of this session
308
+ * (e.g. the worker was SIGKILLed so its exit hooks never ran). Identity-checked
309
+ * so a reused pid is never mis-killed. */
310
+ reapStaleAppServer() {
311
+ const mp = this.markerPath();
312
+ if (!mp || !existsSync(mp))
313
+ return;
314
+ try {
315
+ const [pidStr, markedUrl] = readFileSync(mp, 'utf8').trim().split('\n');
316
+ const pid = parseInt(pidStr, 10);
317
+ if (Number.isInteger(pid) && pid > 0 && isAlive(pid) && this.processIsOurAppServer(pid, markedUrl)) {
318
+ killGroup(pid, 'SIGKILL'); // orphan from a crashed worker — no grace needed
319
+ this.log(`[codex-rpc] reaped stale app-server pid ${pid}`);
320
+ }
321
+ rmSync(mp, { force: true });
322
+ }
323
+ catch { /* best effort */ }
324
+ }
325
+ writeMarker() {
326
+ const mp = this.markerPath();
327
+ if (!mp || !this.child?.pid)
328
+ return;
329
+ // pid + the exact --listen url so a reused pid fails the identity check.
330
+ try {
331
+ mkdirSync(MARKER_DIR, { recursive: true });
332
+ writeFileSync(mp, `${this.child.pid}\n${this.wsUrl}`, { mode: 0o600 });
333
+ }
334
+ catch { /* best effort */ }
335
+ }
336
+ /** Remove the marker ONLY if it still names THIS engine's app-server (pid +
337
+ * wsUrl). Prevents an ABA race: a same-session engine B may have already
338
+ * reaped + rewritten the marker with its own pid/url by the time this (old)
339
+ * engine's child exits late — an unconditional delete would orphan B's live
340
+ * app-server (no marker → next incarnation can't reap it). P1-2. */
341
+ removeMarkerIfOwned() {
342
+ const mp = this.markerPath();
343
+ if (!mp)
344
+ return;
345
+ try {
346
+ const [pidStr, url] = readFileSync(mp, 'utf8').trim().split('\n');
347
+ if (parseInt(pidStr, 10) === this.child?.pid && url === this.wsUrl)
348
+ rmSync(mp, { force: true });
349
+ }
350
+ catch { /* no marker / unreadable → leave it (next reap handles it) */ }
351
+ }
352
+ // ---- internals -----------------------------------------------------------
353
+ waitReady(timeoutMs) {
354
+ const deadline = Date.now() + timeoutMs;
355
+ return new Promise((resolve, reject) => {
356
+ const attempt = () => {
357
+ if (this.closed)
358
+ return reject(new Error('engine closed during startup'));
359
+ const req = httpGet({ host: '127.0.0.1', port: this.port, path: '/readyz', timeout: 1500 }, res => {
360
+ res.resume();
361
+ if (res.statusCode && res.statusCode < 500)
362
+ return resolve();
363
+ retry();
364
+ });
365
+ req.once('error', retry);
366
+ req.once('timeout', () => { req.destroy(); retry(); });
367
+ };
368
+ const retry = () => {
369
+ if (this.closed)
370
+ return reject(new Error('engine closed during startup'));
371
+ if (Date.now() > deadline)
372
+ return reject(new Error(`app-server not ready in ${timeoutMs}ms${this.lastStderr ? `\n${this.lastStderr}` : ''}`));
373
+ setTimeout(attempt, 250);
374
+ };
375
+ attempt();
376
+ });
377
+ }
378
+ connect(timeoutMs) {
379
+ return new Promise((resolve, reject) => {
380
+ const ws = new WebSocket(this.wsUrl);
381
+ const timer = setTimeout(() => { try {
382
+ ws.terminate();
383
+ }
384
+ catch { /* */ } reject(new Error('ws connect timeout')); }, timeoutMs);
385
+ ws.on('open', () => { clearTimeout(timer); this.ws = ws; resolve(); });
386
+ ws.on('message', (data) => this.onMessage(data.toString('utf8')));
387
+ ws.on('error', (err) => { clearTimeout(timer); if (!this.ws)
388
+ reject(err);
389
+ else
390
+ this.failAll(err); });
391
+ ws.on('close', () => { if (!this.closed)
392
+ this.failAll(new Error('ws closed')); });
393
+ });
394
+ }
395
+ request(method, params, opts, onDispatch) {
396
+ const timeoutMs = opts?.timeoutMs ?? this.opts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
397
+ const fatalOnTimeout = opts?.fatalOnTimeout !== false; // default fatal
398
+ const id = this.nextId++;
399
+ return new Promise((resolve, reject) => {
400
+ const timer = setTimeout(() => {
401
+ if (!this.pending.has(id))
402
+ return;
403
+ const err = new Error(`codex app-server request '${method}' timed out after ${timeoutMs}ms`);
404
+ if (fatalOnTimeout) {
405
+ // A connected-but-wedged app-server is FATAL for live turns: rejecting
406
+ // just this request would leave the engine + pane alive and every later
407
+ // turn/start would time out again. Route through failAll so ALL inflight
408
+ // requests reject AND onDead fires — the worker then replaces the pane
409
+ // and re-engages on a fresh app-server (P1-5).
410
+ this.failAll(err);
411
+ }
412
+ else {
413
+ // Non-fatal (the fresh first turn): reject only THIS request and keep
414
+ // the engine alive, so its ambiguity can be resolved against rollout
415
+ // persistence and the viewer can still resume if the turn landed (P1-1).
416
+ this.pending.delete(id);
417
+ reject(err);
418
+ }
419
+ }, timeoutMs);
420
+ timer.unref?.();
421
+ this.pending.set(id, { resolve, reject, timer });
422
+ // onDispatch fires ONLY after send() succeeds (ws was OPEN + no throw) — the
423
+ // frame is then on the socket, so any later failure is "dispatched" and must
424
+ // be treated as ambiguous, never not-sent (Codex P1-1 boundary).
425
+ try {
426
+ this.send({ jsonrpc: '2.0', id, method, params });
427
+ onDispatch?.();
428
+ }
429
+ catch (e) {
430
+ this.pending.delete(id);
431
+ clearTimeout(timer);
432
+ reject(e);
433
+ }
434
+ });
435
+ }
436
+ notify(method, params) {
437
+ this.send(params !== undefined ? { jsonrpc: '2.0', method, params } : { jsonrpc: '2.0', method });
438
+ }
439
+ respond(id, result) {
440
+ try {
441
+ this.send({ jsonrpc: '2.0', id, result });
442
+ }
443
+ catch { /* connection gone */ }
444
+ }
445
+ send(msg) {
446
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
447
+ throw new Error('app-server ws not open');
448
+ this.ws.send(JSON.stringify(msg));
449
+ }
450
+ onMessage(line) {
451
+ let msg;
452
+ try {
453
+ msg = JSON.parse(line);
454
+ }
455
+ catch {
456
+ return;
457
+ }
458
+ // Response to one of our requests.
459
+ if (typeof msg.id === 'number' && (msg.result !== undefined || msg.error !== undefined)) {
460
+ const p = this.pending.get(msg.id);
461
+ if (!p)
462
+ return;
463
+ this.pending.delete(msg.id);
464
+ clearTimeout(p.timer);
465
+ if (msg.error)
466
+ p.reject(new Error(typeof msg.error === 'object' ? JSON.stringify(msg.error) : String(msg.error)));
467
+ else
468
+ p.resolve(msg.result);
469
+ return;
470
+ }
471
+ // Server→client request (approvals / elicitations): auto-answer.
472
+ if (typeof msg.id === 'number' && typeof msg.method === 'string') {
473
+ this.respond(msg.id, autoApproval(msg.method));
474
+ return;
475
+ }
476
+ // Notifications (turn/item/mcp events) are ignored here — the attached TUI
477
+ // renders them; botmux reads the pane as usual.
478
+ }
479
+ failAll(err) {
480
+ if (this.pending.size)
481
+ this.log(`[codex-rpc] ${err.message}`);
482
+ for (const p of this.pending.values()) {
483
+ clearTimeout(p.timer);
484
+ p.reject(err);
485
+ }
486
+ this.pending.clear();
487
+ if (!this.closed && !this.deadNotified) {
488
+ this.deadNotified = true;
489
+ try {
490
+ this.opts.onDead?.();
491
+ }
492
+ catch { /* best effort */ }
493
+ }
494
+ }
495
+ }
496
+ //# sourceMappingURL=codex-rpc-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-rpc-engine.js","sourceRoot":"","sources":["../src/codex-rpc-engine.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,uEAAuE;AACvE,+EAA+E;AAC/E,6EAA6E;AAC7E,kEAAkE;AAClE,EAAE;AACF,0EAA0E;AAC1E,iFAAiF;AACjF,gFAAgF;AAChF,kFAAkF;AAClF,kFAAkF;AAClF,gFAAgF;AAChF,gFAAgF;AAChF,2EAA2E;AAC3E,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,OAAO,EAAE,KAAK,EAAE,YAAY,EAAqB,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAK/B,KAAK,UAAU,YAAY;IACzB,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;YAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9D,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,OAAO,CAAC,GAAW;IAC1B,IAAI,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;AACpE,CAAC;AAED;4EAC4E;AAC5E,SAAS,SAAS,CAAC,GAAW,EAAE,MAAsB;IACpD,IAAI,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,IAAI,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IAAC,CAAC;AACvG,CAAC;AAyBD;mFACmF;AACnF,SAAS,YAAY,CAAC,MAAc;IAClC,IAAI,MAAM,KAAK,kCAAkC;QAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC7F,IAAI,MAAM,KAAK,4BAA4B;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACpE,IAAI,MAAM,KAAK,+BAA+B;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACxG,IAAI,MAAM,KAAK,gBAAgB;QAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC7E,IAAI,MAAM,KAAK,qBAAqB,IAAI,MAAM,KAAK,oBAAoB;QAAE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACrH,yEAAyE;IACzE,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,uBAAuB,CAAC,CAAC;AAE/E;;;;;2EAK2E;AAC3E,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,MAAM,OAAO,cAAc;IAYI;IAXrB,KAAK,CAAgB;IACrB,EAAE,CAAa;IACf,MAAM,GAAG,CAAC,CAAC;IACX,OAAO,GAAG,IAAI,GAAG,EAA2G,CAAC;IAC7H,IAAI,GAAG,CAAC,CAAC;IACT,QAAQ,CAAU;IAClB,MAAM,GAAG,KAAK,CAAC;IACf,YAAY,GAAG,KAAK,CAAC;IACrB,UAAU,GAAG,EAAE,CAAC;IACP,GAAG,CAAQ;IAE5B,YAA6B,IAAwB;QAAxB,SAAI,GAAJ,IAAI,CAAoB;QACnD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,KAAK,KAAa,OAAO,kBAAkB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7D,IAAI,cAAc,KAAyB,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClE,IAAI,YAAY,KAAyB,OAAO,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAElE,4EAA4E;IAC5E,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,MAAM,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,kBAAkB,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE;YAC9F,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG;YAClB,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG;YAClB,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC;YACnC,qEAAqE;YACrE,gEAAgE;YAChE,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,wDAAwD;QAC5E,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE;YAC1C,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1G,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACvC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,yDAAyD;YACrF,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,iCAAiC,IAAI,YAAY,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACxJ,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC7B,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;YAC/B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE;YACjE,YAAY,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE;SACxC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC7B,CAAC;IAED;sEACkE;IAClE,KAAK,CAAC,WAAW;QACf,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;0BAEsB;IACtB,KAAK,CAAC,YAAY,CAAC,QAAgB;QACjC,MAAM,MAAM,GAAS,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;QAC9E,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,8CAA8C;QACzE,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,QAAQ,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,YAAY;QAClB,MAAM,MAAM,GAAS;YACnB,yEAAyE;YACzE,uEAAuE;YACvE,wBAAwB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE;SAC5E,CAAC;QACF,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QACpD,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe;YAAE,MAAM,CAAC,sBAAsB,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;QACzF,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG;YAClB,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,oBAAoB;YAC7B,WAAW,EAAE,QAAQ;YACrB,SAAS,EAAE,KAAK;YAChB,sBAAsB,EAAE,IAAI;YAC5B,MAAM;SACP,CAAC;IACJ,CAAC;IAED;;;;;;;;yEAQqE;IACrE,KAAK,CAAC,QAAQ,CAAC,OAAe,EAAE,mBAA4B,EAAE,IAAuD;QACnH,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAChF,MAAM,MAAM,GAAS;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;YAC3D,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG;YAClB,cAAc,EAAE,OAAO;YACvB,aAAa,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE;SAC5C,CAAC;QACF,IAAI,mBAAmB;YAAE,MAAM,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;QAC1E,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;;;;;;;;;;;6EAgByE;IACzE,KAAK,CAAC,aAAa,CAAC,OAAe,EAAE,mBAAuC,EAAE,YAAoD;QAChI,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACnE,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,MAAM,MAAM,GAAS;YACnB,QAAQ;YACR,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;YAC3D,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG;YAClB,cAAc,EAAE,OAAO;YACvB,aAAa,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE;SAC5C,CAAC;QACF,IAAI,mBAAmB;YAAE,MAAM,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;QAC1E,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACnJ,OAAO,UAAU,CAAC,CAAC,eAAe;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,IAAI,CAAC,GAAG,CAAC,gDAAiD,GAAa,CAAC,OAAO,kBAAkB,CAAC,CAAC;gBACnG,OAAO,UAAU,CAAC;YACpB,CAAC;YACD,uEAAuE;YACvE,6EAA6E;YAC7E,uDAAuD;YACvD,IAAI,CAAC,GAAG,CAAC,mDAAoD,GAAa,CAAC,OAAO,2CAA2C,CAAC,CAAC;YAC/H,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC5C,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,IAAI;QACF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC;YAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;QACtD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC;QAC5B,IAAI,GAAG,EAAE,CAAC;YACR,0EAA0E;YAC1E,uEAAuE;YACvE,4EAA4E;YAC5E,iEAAiE;YACjE,IAAI,CAAC;gBAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;YAC/D,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC;oBAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;YAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YAC/G,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QACd,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,6EAA6E;IAErE,UAAU;QAChB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,SAAS,CAAC;QAC3C,OAAO,IAAI,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,CAAC;IACxD,CAAC;IAED;;;;6CAIyC;IACjC,qBAAqB,CAAC,GAAW,EAAE,SAAkB;QAC3D,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,IAAI,CAAC;YAAC,IAAI,GAAG,YAAY,CAAC,SAAS,GAAG,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAAC,CAAC;QAChF,MAAM,CAAC;YACL,IAAI,CAAC;gBAAC,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;YACjI,MAAM,CAAC;gBAAC,OAAO,KAAK,CAAC;YAAC,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/C,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,KAAK,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;+CAE2C;IACnC,kBAAkB;QACxB,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAAE,OAAO;QACnC,IAAI,CAAC;YACH,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxE,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACjC,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;gBACnG,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,iDAAiD;gBAC5E,IAAI,CAAC,GAAG,CAAC,2CAA2C,GAAG,EAAE,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC/B,CAAC;IAEO,WAAW;QACjB,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG;YAAE,OAAO;QACpC,yEAAyE;QACzE,IAAI,CAAC;YAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAAC,aAAa,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAAC,CAAC;QAC3H,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC7B,CAAC;IAED;;;;yEAIqE;IAC7D,mBAAmB;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,IAAI,CAAC;YACH,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClE,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,KAAK,IAAI,CAAC,KAAK;gBAAE,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClG,CAAC;QAAC,MAAM,CAAC,CAAC,8DAA8D,CAAC,CAAC;IAC5E,CAAC;IAED,6EAA6E;IAErE,SAAS,CAAC,SAAiB;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,MAAM,OAAO,GAAG,GAAS,EAAE;gBACzB,IAAI,IAAI,CAAC,MAAM;oBAAE,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;gBAC1E,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE;oBAChG,GAAG,CAAC,MAAM,EAAE,CAAC;oBACb,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG;wBAAE,OAAO,OAAO,EAAE,CAAC;oBAC7D,KAAK,EAAE,CAAC;gBACV,CAAC,CAAC,CAAC;gBACH,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACzB,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACzD,CAAC,CAAC;YACF,MAAM,KAAK,GAAG,GAAS,EAAE;gBACvB,IAAI,IAAI,CAAC,MAAM;oBAAE,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;gBAC1E,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ;oBAAE,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,SAAS,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC9I,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC3B,CAAC,CAAC;YACF,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,OAAO,CAAC,SAAiB;QAC/B,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;gBAAC,EAAE,CAAC,SAAS,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAChI,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1E,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;gBAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5G,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpF,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,OAAO,CACb,MAAc,EACd,MAAe,EACf,IAAuD,EACvD,UAAuB;QAEvB,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,kBAAkB,CAAC;QACtF,MAAM,cAAc,GAAG,IAAI,EAAE,cAAc,KAAK,KAAK,CAAC,CAAC,gBAAgB;QACvE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;oBAAE,OAAO;gBAClC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,6BAA6B,MAAM,qBAAqB,SAAS,IAAI,CAAC,CAAC;gBAC7F,IAAI,cAAc,EAAE,CAAC;oBACnB,uEAAuE;oBACvE,wEAAwE;oBACxE,yEAAyE;oBACzE,uEAAuE;oBACvE,+CAA+C;oBAC/C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACpB,CAAC;qBAAM,CAAC;oBACN,sEAAsE;oBACtE,qEAAqE;oBACrE,yEAAyE;oBACzE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YACjD,6EAA6E;YAC7E,6EAA6E;YAC7E,iEAAiE;YACjE,IAAI,CAAC;gBAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;gBAAC,UAAU,EAAE,EAAE,CAAC;YAAC,CAAC;YAC1E,OAAO,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAAC,YAAY,CAAC,KAAK,CAAC,CAAC;gBAAC,MAAM,CAAC,CAAU,CAAC,CAAC;YAAC,CAAC;QACjF,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,MAAc,EAAE,MAAgB;QAC7C,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACpG,CAAC;IAEO,OAAO,CAAC,EAAU,EAAE,MAAe;QACzC,IAAI,CAAC;YAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC;IACpF,CAAC;IAEO,IAAI,CAAC,GAAS;QACpB,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACjG,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,CAAC;IAEO,SAAS,CAAC,IAAY;QAC5B,IAAI,GAAS,CAAC;QACd,IAAI,CAAC;YAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO;QAAC,CAAC;QACjD,mCAAmC;QACnC,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE,CAAC;YACxF,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,CAAC,CAAC;gBAAE,OAAO;YACf,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC5B,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACtB,IAAI,GAAG,CAAC,KAAK;gBAAE,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;;gBAC7G,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC3B,OAAO;QACT,CAAC;QACD,iEAAiE;QACjE,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACjE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QACD,2EAA2E;QAC3E,gDAAgD;IAClD,CAAC;IAEO,OAAO,CAAC,GAAU;QACxB,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAChF,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,IAAI,CAAC;gBAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;CACF"}