{"version":3,"file":"requestProcessor.cjs","names":["accessor: ConnectionAccessor","wakeSignal: WakeSignal","callbacks: ConnectionCoreCallbacks","logger: Logger","ConnectionState","parseGatewayExecutorRequest","ensureUnsharedArrayBuffer","ConnectMessage","GatewayMessageType","WorkerRequestAckData","extendLeaseInterval: ReturnType<typeof setInterval> | undefined","WorkerRequestExtendLeaseData","WAKE_REASON","parseWorkerReplyAck","WorkerRequestExtendLeaseAckData"],"sources":["../../../../../src/components/connect/strategies/core/requestProcessor.ts"],"sourcesContent":["/**\n * Processes incoming executor requests, manages lease extensions, and handles\n * reply acknowledgements.\n *\n * Extracted from ConnectionCore so the reconcile loop orchestrator only\n * dispatches messages to this module rather than containing the full\n * execution flow inline.\n */\n\nimport type { Logger } from \"../../../../middleware/logger.ts\";\nimport {\n  ConnectMessage,\n  type ConnectMessage as ConnectMessageType,\n  GatewayMessageType,\n  WorkerRequestAckData,\n  WorkerRequestExtendLeaseAckData,\n  WorkerRequestExtendLeaseData,\n} from \"../../../../proto/src/components/connect/protobuf/connect.ts\";\nimport { ensureUnsharedArrayBuffer } from \"../../buffer.ts\";\nimport {\n  parseGatewayExecutorRequest,\n  parseWorkerReplyAck,\n} from \"../../messages.ts\";\nimport { ConnectionState } from \"../../types.ts\";\nimport type { Connection, ConnectionCoreCallbacks } from \"./connection.ts\";\nimport {\n  type ConnectionAccessor,\n  WAKE_REASON,\n  type WakeSignal,\n} from \"./types.ts\";\n\nfunction toError(value: unknown): Error {\n  if (value instanceof Error) {\n    return value;\n  }\n  return new Error(String(value));\n}\n\nexport class RequestProcessor {\n  constructor(\n    private readonly accessor: ConnectionAccessor,\n    private readonly wakeSignal: WakeSignal,\n    private readonly callbacks: ConnectionCoreCallbacks,\n    private readonly logger: Logger,\n  ) {}\n\n  /** Handle an incoming executor request. */\n  async handleExecutorRequest(\n    connectMessage: ConnectMessageType,\n    conn: Connection,\n  ): Promise<void> {\n    const currentState = this.callbacks.getState();\n    if (currentState !== ConnectionState.ACTIVE) {\n      this.logger.warn(\n        { connectionId: conn.id },\n        \"Received request while not active, skipping\",\n      );\n      return;\n    }\n\n    const gatewayExecutorRequest = parseGatewayExecutorRequest(\n      connectMessage.payload,\n    );\n\n    this.logger.debug(\n      {\n        requestId: gatewayExecutorRequest.requestId,\n        appId: gatewayExecutorRequest.appId,\n        appName: gatewayExecutorRequest.appName,\n        functionSlug: gatewayExecutorRequest.functionSlug,\n        stepId: gatewayExecutorRequest.stepId,\n        connectionId: conn.id,\n      },\n      \"Received gateway executor request\",\n    );\n\n    if (\n      typeof gatewayExecutorRequest.appName !== \"string\" ||\n      gatewayExecutorRequest.appName.length === 0\n    ) {\n      this.logger.warn(\n        {\n          requestId: gatewayExecutorRequest.requestId,\n          appId: gatewayExecutorRequest.appId,\n          functionSlug: gatewayExecutorRequest.functionSlug,\n          stepId: gatewayExecutorRequest.stepId,\n          connectionId: conn.id,\n        },\n        \"No app name in request, skipping\",\n      );\n      return;\n    }\n\n    if (!this.accessor.appIds.includes(gatewayExecutorRequest.appName)) {\n      this.logger.warn(\n        {\n          requestId: gatewayExecutorRequest.requestId,\n          appId: gatewayExecutorRequest.appId,\n          appName: gatewayExecutorRequest.appName,\n          functionSlug: gatewayExecutorRequest.functionSlug,\n          stepId: gatewayExecutorRequest.stepId,\n          connectionId: conn.id,\n        },\n        \"No request handler found for app, skipping\",\n      );\n      return;\n    }\n\n    // Send ACK\n    conn.ws.send(\n      ensureUnsharedArrayBuffer(\n        ConnectMessage.encode(\n          ConnectMessage.create({\n            kind: GatewayMessageType.WORKER_REQUEST_ACK,\n            payload: WorkerRequestAckData.encode(\n              WorkerRequestAckData.create({\n                accountId: gatewayExecutorRequest.accountId,\n                envId: gatewayExecutorRequest.envId,\n                appId: gatewayExecutorRequest.appId,\n                functionSlug: gatewayExecutorRequest.functionSlug,\n                requestId: gatewayExecutorRequest.requestId,\n                stepId: gatewayExecutorRequest.stepId,\n                userTraceCtx: gatewayExecutorRequest.userTraceCtx,\n                systemTraceCtx: gatewayExecutorRequest.systemTraceCtx,\n                runId: gatewayExecutorRequest.runId,\n              }),\n            ).finish(),\n          }),\n        ).finish(),\n      ),\n    );\n\n    this.accessor.inProgressRequests.wg.add(1);\n    this.accessor.inProgressRequests.requestLeases[\n      gatewayExecutorRequest.requestId\n    ] = gatewayExecutorRequest.leaseId;\n    const leaseAcquiredAt = Date.now();\n    this.accessor.inProgressRequests.requestMeta[\n      gatewayExecutorRequest.requestId\n    ] = {\n      requestId: gatewayExecutorRequest.requestId,\n      runId: gatewayExecutorRequest.runId,\n      stepId: gatewayExecutorRequest.stepId,\n      appId: gatewayExecutorRequest.appId,\n      envId: gatewayExecutorRequest.envId,\n      functionSlug: gatewayExecutorRequest.functionSlug,\n      accountId: gatewayExecutorRequest.accountId,\n      leaseAcquiredAt,\n      leaseLastExtendedAt: leaseAcquiredAt,\n    };\n\n    const inFlightCount = Object.keys(\n      this.accessor.inProgressRequests.requestLeases,\n    ).length;\n    this.logger.debug(\n      {\n        requestId: gatewayExecutorRequest.requestId,\n        functionSlug: gatewayExecutorRequest.functionSlug,\n        inFlightCount,\n      },\n      \"Request acknowledged\",\n    );\n\n    const startedAt = Date.now();\n\n    // Start lease extension interval\n    const originalWs = conn.ws;\n    const originalConnectionId = conn.id;\n    let extendLeaseInterval: ReturnType<typeof setInterval> | undefined;\n    extendLeaseInterval = setInterval(() => {\n      const currentLeaseId =\n        this.accessor.inProgressRequests.requestLeases[\n          gatewayExecutorRequest.requestId\n        ];\n      if (!currentLeaseId) {\n        clearInterval(extendLeaseInterval);\n        return;\n      }\n\n      // Use the current live connection's WebSocket for lease extensions.\n      // During a drain, the original WebSocket may be closed by the gateway\n      // while the request is still in flight.\n      const latestConn = {\n        ws: this.accessor.activeConnection?.ws ?? originalWs,\n        id: this.accessor.activeConnection?.id ?? originalConnectionId,\n      };\n\n      this.logger.debug(\n        {\n          connectionId: latestConn.id,\n          leaseId: currentLeaseId,\n          requestId: gatewayExecutorRequest.requestId,\n          functionSlug: gatewayExecutorRequest.functionSlug,\n          runId: gatewayExecutorRequest.runId,\n          stepId: gatewayExecutorRequest.stepId,\n        },\n        \"Extending lease\",\n      );\n\n      if (latestConn.ws.readyState !== WebSocket.OPEN) {\n        this.logger.warn(\n          {\n            connectionId: latestConn.id,\n            requestId: gatewayExecutorRequest.requestId,\n          },\n          \"Cannot extend lease, no open WebSocket available\",\n        );\n        return;\n      }\n\n      try {\n        latestConn.ws.send(\n          ensureUnsharedArrayBuffer(\n            ConnectMessage.encode(\n              ConnectMessage.create({\n                kind: GatewayMessageType.WORKER_REQUEST_EXTEND_LEASE,\n                payload: WorkerRequestExtendLeaseData.encode(\n                  WorkerRequestExtendLeaseData.create({\n                    accountId: gatewayExecutorRequest.accountId,\n                    envId: gatewayExecutorRequest.envId,\n                    appId: gatewayExecutorRequest.appId,\n                    functionSlug: gatewayExecutorRequest.functionSlug,\n                    requestId: gatewayExecutorRequest.requestId,\n                    stepId: gatewayExecutorRequest.stepId,\n                    runId: gatewayExecutorRequest.runId,\n                    userTraceCtx: gatewayExecutorRequest.userTraceCtx,\n                    systemTraceCtx: gatewayExecutorRequest.systemTraceCtx,\n                    leaseId: currentLeaseId,\n                  }),\n                ).finish(),\n              }),\n            ).finish(),\n          ),\n        );\n        const meta =\n          this.accessor.inProgressRequests.requestMeta[\n            gatewayExecutorRequest.requestId\n          ];\n        if (meta) meta.leaseLastExtendedAt = Date.now();\n      } catch (err) {\n        this.logger.warn(\n          {\n            connectionId: latestConn.id,\n            requestId: gatewayExecutorRequest.requestId,\n            err: toError(err),\n          },\n          \"Failed to send lease extension\",\n        );\n      }\n    }, conn.extendLeaseIntervalMs);\n\n    try {\n      const responseBytes = await this.callbacks.handleExecutionRequest(\n        gatewayExecutorRequest,\n      );\n\n      const durationMs = Date.now() - startedAt;\n      this.logger.debug(\n        {\n          requestId: gatewayExecutorRequest.requestId,\n          functionSlug: gatewayExecutorRequest.functionSlug,\n          durationMs,\n        },\n        \"Request execution completed\",\n      );\n\n      if (!this.accessor.activeConnection) {\n        this.logger.warn(\n          { requestId: gatewayExecutorRequest.requestId },\n          \"No current WebSocket, buffering response\",\n        );\n        if (this.callbacks.onBufferResponse) {\n          this.callbacks.onBufferResponse(\n            gatewayExecutorRequest.requestId,\n            responseBytes,\n          );\n        }\n        return;\n      }\n\n      this.logger.debug(\n        {\n          connectionId: this.accessor.activeConnection.id,\n          requestId: gatewayExecutorRequest.requestId,\n        },\n        \"Sending worker reply\",\n      );\n\n      this.accessor.activeConnection.ws.send(\n        ensureUnsharedArrayBuffer(\n          ConnectMessage.encode(\n            ConnectMessage.create({\n              kind: GatewayMessageType.WORKER_REPLY,\n              payload: responseBytes,\n            }),\n          ).finish(),\n        ),\n      );\n    } catch (err) {\n      const durationMs = Date.now() - startedAt;\n      this.logger.warn(\n        {\n          requestId: gatewayExecutorRequest.requestId,\n          durationMs,\n          err: toError(err),\n        },\n        \"Execution error\",\n      );\n    } finally {\n      this.accessor.inProgressRequests.wg.done();\n      delete this.accessor.inProgressRequests.requestLeases[\n        gatewayExecutorRequest.requestId\n      ];\n      delete this.accessor.inProgressRequests.requestMeta[\n        gatewayExecutorRequest.requestId\n      ];\n      clearInterval(extendLeaseInterval);\n\n      const remainingInFlight = Object.keys(\n        this.accessor.inProgressRequests.requestLeases,\n      ).length;\n      this.logger.debug(\n        {\n          requestId: gatewayExecutorRequest.requestId,\n          remainingInFlight,\n        },\n        \"Request finished\",\n      );\n\n      // Wake the loop if shutdown is pending and this was the last request\n      if (this.accessor.shutdownRequested && !this.hasInFlightRequests()) {\n        this.wakeSignal.wake(WAKE_REASON.RequestFinishedOnShutdown);\n      }\n    }\n  }\n\n  /** Handle a reply ACK from the gateway. */\n  handleReplyAck(\n    connectMessage: ConnectMessageType,\n    connectionId: string,\n  ): void {\n    const replyAck = parseWorkerReplyAck(connectMessage.payload);\n\n    this.logger.debug(\n      { connectionId, requestId: replyAck.requestId },\n      \"Acknowledging reply ack\",\n    );\n\n    this.callbacks.onReplyAck?.(replyAck.requestId);\n  }\n\n  /** Handle a lease extension ACK from the gateway. */\n  handleExtendLeaseAck(\n    connectMessage: ConnectMessageType,\n    connectionId: string,\n  ): void {\n    const extendLeaseAck = WorkerRequestExtendLeaseAckData.decode(\n      connectMessage.payload,\n    );\n\n    // Late lease-extend ACKs can arrive after a request has already cleaned up\n    // both maps in the completion or lease-lost path. This handler stays\n    // synchronous, so once we observe the request missing from either map we\n    // can safely ignore the ACK instead of recreating a stale lease entry.\n    const hasLease = Object.hasOwn(\n      this.accessor.inProgressRequests.requestLeases,\n      extendLeaseAck.requestId,\n    );\n    const meta =\n      this.accessor.inProgressRequests.requestMeta[extendLeaseAck.requestId];\n    if (!hasLease || !meta) {\n      this.logger.debug(\n        {\n          connectionId,\n          requestId: extendLeaseAck.requestId,\n          newLeaseId: extendLeaseAck.newLeaseId,\n          hadLease: hasLease,\n          hadMeta: !!meta,\n        },\n        \"Ignoring extend lease ack for non-in-flight request\",\n      );\n      return;\n    }\n\n    this.logger.debug(\n      { connectionId, newLeaseId: extendLeaseAck.newLeaseId },\n      \"Received extend lease ack\",\n    );\n\n    if (extendLeaseAck.newLeaseId) {\n      this.accessor.inProgressRequests.requestLeases[extendLeaseAck.requestId] =\n        extendLeaseAck.newLeaseId;\n    } else {\n      this.logger.error(\n        {\n          connectionId,\n          requestId: extendLeaseAck.requestId,\n          functionSlug: meta?.functionSlug,\n          runId: meta?.runId,\n          stepId: meta?.stepId,\n        },\n        \"Lease lost: the server did not renew the lease for this request. \" +\n          \"Another worker may have claimed it. The in-progress execution \" +\n          \"will continue but its result may be discarded.\",\n      );\n      delete this.accessor.inProgressRequests.requestLeases[\n        extendLeaseAck.requestId\n      ];\n      // Also drop meta so the shutdown dump helper and debug-state snapshot\n      // don't report a request we've explicitly released the lease for.\n      delete this.accessor.inProgressRequests.requestMeta[\n        extendLeaseAck.requestId\n      ];\n\n      // If this was the last in-flight request and a shutdown has been\n      // requested, wake the reconcile loop so close() can observe the\n      // empty lease map and exit. Without this, the loop stays parked on\n      // wakeSignal.promise because the finally-block decrement in\n      // handleExecutorRequest never runs (user code is still hanging).\n      if (this.accessor.shutdownRequested && !this.hasInFlightRequests()) {\n        this.wakeSignal.wake(WAKE_REASON.LeaseLostOnShutdown);\n      }\n    }\n  }\n\n  private hasInFlightRequests(): boolean {\n    return (\n      Object.keys(this.accessor.inProgressRequests.requestLeases).length > 0\n    );\n  }\n}\n"],"mappings":";;;;;;;AA+BA,SAAS,QAAQ,OAAuB;AACtC,KAAI,iBAAiB,MACnB,QAAO;AAET,QAAO,IAAI,MAAM,OAAO,MAAM,CAAC;;AAGjC,IAAa,mBAAb,MAA8B;CAC5B,YACE,AAAiBA,UACjB,AAAiBC,YACjB,AAAiBC,WACjB,AAAiBC,QACjB;EAJiB;EACA;EACA;EACA;;;CAInB,MAAM,sBACJ,gBACA,MACe;AAEf,MADqB,KAAK,UAAU,UAAU,KACzBC,8BAAgB,QAAQ;AAC3C,QAAK,OAAO,KACV,EAAE,cAAc,KAAK,IAAI,EACzB,8CACD;AACD;;EAGF,MAAM,yBAAyBC,6CAC7B,eAAe,QAChB;AAED,OAAK,OAAO,MACV;GACE,WAAW,uBAAuB;GAClC,OAAO,uBAAuB;GAC9B,SAAS,uBAAuB;GAChC,cAAc,uBAAuB;GACrC,QAAQ,uBAAuB;GAC/B,cAAc,KAAK;GACpB,EACD,oCACD;AAED,MACE,OAAO,uBAAuB,YAAY,YAC1C,uBAAuB,QAAQ,WAAW,GAC1C;AACA,QAAK,OAAO,KACV;IACE,WAAW,uBAAuB;IAClC,OAAO,uBAAuB;IAC9B,cAAc,uBAAuB;IACrC,QAAQ,uBAAuB;IAC/B,cAAc,KAAK;IACpB,EACD,mCACD;AACD;;AAGF,MAAI,CAAC,KAAK,SAAS,OAAO,SAAS,uBAAuB,QAAQ,EAAE;AAClE,QAAK,OAAO,KACV;IACE,WAAW,uBAAuB;IAClC,OAAO,uBAAuB;IAC9B,SAAS,uBAAuB;IAChC,cAAc,uBAAuB;IACrC,QAAQ,uBAAuB;IAC/B,cAAc,KAAK;IACpB,EACD,6CACD;AACD;;AAIF,OAAK,GAAG,KACNC,yCACEC,+BAAe,OACbA,+BAAe,OAAO;GACpB,MAAMC,mCAAmB;GACzB,SAASC,qCAAqB,OAC5BA,qCAAqB,OAAO;IAC1B,WAAW,uBAAuB;IAClC,OAAO,uBAAuB;IAC9B,OAAO,uBAAuB;IAC9B,cAAc,uBAAuB;IACrC,WAAW,uBAAuB;IAClC,QAAQ,uBAAuB;IAC/B,cAAc,uBAAuB;IACrC,gBAAgB,uBAAuB;IACvC,OAAO,uBAAuB;IAC/B,CAAC,CACH,CAAC,QAAQ;GACX,CAAC,CACH,CAAC,QAAQ,CACX,CACF;AAED,OAAK,SAAS,mBAAmB,GAAG,IAAI,EAAE;AAC1C,OAAK,SAAS,mBAAmB,cAC/B,uBAAuB,aACrB,uBAAuB;EAC3B,MAAM,kBAAkB,KAAK,KAAK;AAClC,OAAK,SAAS,mBAAmB,YAC/B,uBAAuB,aACrB;GACF,WAAW,uBAAuB;GAClC,OAAO,uBAAuB;GAC9B,QAAQ,uBAAuB;GAC/B,OAAO,uBAAuB;GAC9B,OAAO,uBAAuB;GAC9B,cAAc,uBAAuB;GACrC,WAAW,uBAAuB;GAClC;GACA,qBAAqB;GACtB;EAED,MAAM,gBAAgB,OAAO,KAC3B,KAAK,SAAS,mBAAmB,cAClC,CAAC;AACF,OAAK,OAAO,MACV;GACE,WAAW,uBAAuB;GAClC,cAAc,uBAAuB;GACrC;GACD,EACD,uBACD;EAED,MAAM,YAAY,KAAK,KAAK;EAG5B,MAAM,aAAa,KAAK;EACxB,MAAM,uBAAuB,KAAK;EAClC,IAAIC;AACJ,wBAAsB,kBAAkB;GACtC,MAAM,iBACJ,KAAK,SAAS,mBAAmB,cAC/B,uBAAuB;AAE3B,OAAI,CAAC,gBAAgB;AACnB,kBAAc,oBAAoB;AAClC;;GAMF,MAAM,aAAa;IACjB,IAAI,KAAK,SAAS,kBAAkB,MAAM;IAC1C,IAAI,KAAK,SAAS,kBAAkB,MAAM;IAC3C;AAED,QAAK,OAAO,MACV;IACE,cAAc,WAAW;IACzB,SAAS;IACT,WAAW,uBAAuB;IAClC,cAAc,uBAAuB;IACrC,OAAO,uBAAuB;IAC9B,QAAQ,uBAAuB;IAChC,EACD,kBACD;AAED,OAAI,WAAW,GAAG,eAAe,UAAU,MAAM;AAC/C,SAAK,OAAO,KACV;KACE,cAAc,WAAW;KACzB,WAAW,uBAAuB;KACnC,EACD,mDACD;AACD;;AAGF,OAAI;AACF,eAAW,GAAG,KACZJ,yCACEC,+BAAe,OACbA,+BAAe,OAAO;KACpB,MAAMC,mCAAmB;KACzB,SAASG,6CAA6B,OACpCA,6CAA6B,OAAO;MAClC,WAAW,uBAAuB;MAClC,OAAO,uBAAuB;MAC9B,OAAO,uBAAuB;MAC9B,cAAc,uBAAuB;MACrC,WAAW,uBAAuB;MAClC,QAAQ,uBAAuB;MAC/B,OAAO,uBAAuB;MAC9B,cAAc,uBAAuB;MACrC,gBAAgB,uBAAuB;MACvC,SAAS;MACV,CAAC,CACH,CAAC,QAAQ;KACX,CAAC,CACH,CAAC,QAAQ,CACX,CACF;IACD,MAAM,OACJ,KAAK,SAAS,mBAAmB,YAC/B,uBAAuB;AAE3B,QAAI,KAAM,MAAK,sBAAsB,KAAK,KAAK;YACxC,KAAK;AACZ,SAAK,OAAO,KACV;KACE,cAAc,WAAW;KACzB,WAAW,uBAAuB;KAClC,KAAK,QAAQ,IAAI;KAClB,EACD,iCACD;;KAEF,KAAK,sBAAsB;AAE9B,MAAI;GACF,MAAM,gBAAgB,MAAM,KAAK,UAAU,uBACzC,uBACD;GAED,MAAM,aAAa,KAAK,KAAK,GAAG;AAChC,QAAK,OAAO,MACV;IACE,WAAW,uBAAuB;IAClC,cAAc,uBAAuB;IACrC;IACD,EACD,8BACD;AAED,OAAI,CAAC,KAAK,SAAS,kBAAkB;AACnC,SAAK,OAAO,KACV,EAAE,WAAW,uBAAuB,WAAW,EAC/C,2CACD;AACD,QAAI,KAAK,UAAU,iBACjB,MAAK,UAAU,iBACb,uBAAuB,WACvB,cACD;AAEH;;AAGF,QAAK,OAAO,MACV;IACE,cAAc,KAAK,SAAS,iBAAiB;IAC7C,WAAW,uBAAuB;IACnC,EACD,uBACD;AAED,QAAK,SAAS,iBAAiB,GAAG,KAChCL,yCACEC,+BAAe,OACbA,+BAAe,OAAO;IACpB,MAAMC,mCAAmB;IACzB,SAAS;IACV,CAAC,CACH,CAAC,QAAQ,CACX,CACF;WACM,KAAK;GACZ,MAAM,aAAa,KAAK,KAAK,GAAG;AAChC,QAAK,OAAO,KACV;IACE,WAAW,uBAAuB;IAClC;IACA,KAAK,QAAQ,IAAI;IAClB,EACD,kBACD;YACO;AACR,QAAK,SAAS,mBAAmB,GAAG,MAAM;AAC1C,UAAO,KAAK,SAAS,mBAAmB,cACtC,uBAAuB;AAEzB,UAAO,KAAK,SAAS,mBAAmB,YACtC,uBAAuB;AAEzB,iBAAc,oBAAoB;GAElC,MAAM,oBAAoB,OAAO,KAC/B,KAAK,SAAS,mBAAmB,cAClC,CAAC;AACF,QAAK,OAAO,MACV;IACE,WAAW,uBAAuB;IAClC;IACD,EACD,mBACD;AAGD,OAAI,KAAK,SAAS,qBAAqB,CAAC,KAAK,qBAAqB,CAChE,MAAK,WAAW,KAAKI,4BAAY,0BAA0B;;;;CAMjE,eACE,gBACA,cACM;EACN,MAAM,WAAWC,qCAAoB,eAAe,QAAQ;AAE5D,OAAK,OAAO,MACV;GAAE;GAAc,WAAW,SAAS;GAAW,EAC/C,0BACD;AAED,OAAK,UAAU,aAAa,SAAS,UAAU;;;CAIjD,qBACE,gBACA,cACM;EACN,MAAM,iBAAiBC,gDAAgC,OACrD,eAAe,QAChB;EAMD,MAAM,WAAW,OAAO,OACtB,KAAK,SAAS,mBAAmB,eACjC,eAAe,UAChB;EACD,MAAM,OACJ,KAAK,SAAS,mBAAmB,YAAY,eAAe;AAC9D,MAAI,CAAC,YAAY,CAAC,MAAM;AACtB,QAAK,OAAO,MACV;IACE;IACA,WAAW,eAAe;IAC1B,YAAY,eAAe;IAC3B,UAAU;IACV,SAAS,CAAC,CAAC;IACZ,EACD,sDACD;AACD;;AAGF,OAAK,OAAO,MACV;GAAE;GAAc,YAAY,eAAe;GAAY,EACvD,4BACD;AAED,MAAI,eAAe,WACjB,MAAK,SAAS,mBAAmB,cAAc,eAAe,aAC5D,eAAe;OACZ;AACL,QAAK,OAAO,MACV;IACE;IACA,WAAW,eAAe;IAC1B,cAAc,MAAM;IACpB,OAAO,MAAM;IACb,QAAQ,MAAM;IACf,EACD,gLAGD;AACD,UAAO,KAAK,SAAS,mBAAmB,cACtC,eAAe;AAIjB,UAAO,KAAK,SAAS,mBAAmB,YACtC,eAAe;AAQjB,OAAI,KAAK,SAAS,qBAAqB,CAAC,KAAK,qBAAqB,CAChE,MAAK,WAAW,KAAKF,4BAAY,oBAAoB;;;CAK3D,AAAQ,sBAA+B;AACrC,SACE,OAAO,KAAK,KAAK,SAAS,mBAAmB,cAAc,CAAC,SAAS"}