@midscene/playground 1.8.6 → 1.8.7-beta-20260527113633.0

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.
@@ -294,10 +294,13 @@ class PlaygroundServer {
294
294
  scrcpyPort: this.scrcpyPort
295
295
  });
296
296
  }
297
+ isEffectivelyConnected() {
298
+ const rawConnected = this.sessionManager ? Boolean(this._activeConnection.session?.connected && this._activeConnection.agent) : Boolean(this._activeConnection.agent);
299
+ return rawConnected || !this._agentReady;
300
+ }
297
301
  getSessionInfo() {
298
- const connected = this.sessionManager ? Boolean(this._activeConnection.session?.connected && this._activeConnection.agent) : Boolean(this._activeConnection.agent);
299
302
  return {
300
- connected,
303
+ connected: this.isEffectivelyConnected(),
301
304
  displayName: this._activeConnection.session?.displayName,
302
305
  metadata: {
303
306
  ...this._activeConnection.session?.metadata || {}
@@ -307,11 +310,10 @@ class PlaygroundServer {
307
310
  };
308
311
  }
309
312
  buildSessionMetadata() {
310
- const sessionConnected = this.sessionManager ? Boolean(this._activeConnection.session?.connected && this._activeConnection.agent) : Boolean(this._activeConnection.agent);
311
313
  return {
312
314
  ...this._basePreparedMetadata || {},
313
315
  ...this._activeConnection.session?.metadata || {},
314
- sessionConnected,
316
+ sessionConnected: this.isEffectivelyConnected(),
315
317
  sessionDisplayName: this._activeConnection.session?.displayName,
316
318
  setupState: this.sessionSetupState,
317
319
  ...this.sessionSetupBlockingReason ? {
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","sources":["../../src/server.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport type { Server } from 'node:http';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type {\n DeviceAction,\n ExecutionDump,\n ExecutionTask,\n ExecutorContext,\n} from '@midscene/core';\nimport { ReportActionDump, runConnectivityTest } from '@midscene/core';\nimport type { Agent as PageAgent } from '@midscene/core/agent';\nimport { getTmpDir } from '@midscene/core/utils';\nimport { PLAYGROUND_SERVER_PORT } from '@midscene/shared/constants';\nimport {\n globalModelConfigManager,\n overrideAIConfig,\n} from '@midscene/shared/env';\nimport { generateElementByPoint } from '@midscene/shared/extractor';\nimport { getDebug } from '@midscene/shared/logger';\nimport { uuid } from '@midscene/shared/utils';\nimport express, { type Request, type Response } from 'express';\nimport { executeAction, formatErrorMessage } from './common';\nimport { MjpegStreamHandler } from './mjpeg-stream-handler';\nimport type {\n PlaygroundCreatedSession,\n PlaygroundExecutionHooks,\n PlaygroundPreviewDescriptor,\n PlaygroundSessionManager,\n PlaygroundSessionSetup,\n PlaygroundSessionState,\n PlaygroundSessionTarget,\n PlaygroundSidecar,\n PreparedPlaygroundPlatform,\n} from './platform';\nimport { PointerInputError, dispatchPointer } from './pointer-dispatch';\nimport {\n type PlaygroundRuntimeInfo,\n buildRuntimeInfo,\n} from './runtime-metadata';\nimport type { AgentFactory } from './types';\n\nimport 'dotenv/config';\n\nconst defaultPort = PLAYGROUND_SERVER_PORT;\n\nfunction serializeAiConfigSignature(aiConfig: Record<string, unknown>): string {\n return JSON.stringify(\n Object.entries(aiConfig).sort(([leftKey], [rightKey]) =>\n leftKey.localeCompare(rightKey),\n ),\n );\n}\n\n/**\n * Recursively serialize a Zod field into a plain object that preserves\n * the `_def` metadata the client relies on (typeName, innerType, values,\n * defaultValue, description, shape, etc.).\n */\nexport function serializeZodField(field: any): any {\n if (!field || typeof field !== 'object') return field;\n\n const def = field._def;\n if (!def || typeof def !== 'object') return field;\n\n const typeName: string | undefined = def.typeName;\n\n const result: Record<string, any> = {\n _def: {\n typeName,\n },\n };\n\n // Preserve description\n if (def.description) {\n result._def.description = def.description;\n }\n\n // Wrapper types (ZodOptional, ZodDefault, ZodNullable) – recurse into innerType\n if (def.innerType) {\n result._def.innerType = serializeZodField(def.innerType);\n }\n\n // ZodDefault – preserve defaultValue as a serializable plain value\n if (typeName === 'ZodDefault' && typeof def.defaultValue === 'function') {\n try {\n result._def._serializedDefaultValue = def.defaultValue();\n } catch {\n // ignore\n }\n }\n\n // ZodEnum – preserve values array\n if (typeName === 'ZodEnum' && Array.isArray(def.values)) {\n result._def.values = def.values;\n }\n\n // ZodObject – recurse into shape\n if (typeName === 'ZodObject') {\n const rawShape = typeof def.shape === 'function' ? def.shape() : def.shape;\n if (rawShape && typeof rawShape === 'object') {\n const serializedShape: Record<string, any> = {};\n for (const [k, v] of Object.entries(rawShape)) {\n serializedShape[k] = serializeZodField(v);\n }\n result._def.shape = serializedShape;\n result.shape = serializedShape;\n }\n }\n\n // Copy top-level description for compatibility\n if (field.description) {\n result.description = field.description;\n }\n\n return result;\n}\n\n// Static path for playground files\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst STATIC_PATH = join(__dirname, '..', '..', 'static');\n\nconst debugScreenshot = getDebug('playground:screenshot', { console: true });\nconst debugMjpeg = getDebug('playground:mjpeg', { console: true });\n\n/**\n * Thrown when a caller supplies an /interact body that fails validation\n * (missing x/y, missing keyName for KeyboardPress, etc.). Distinct from a\n * downstream device failure so the route handler can map this to HTTP 400.\n */\nexport class InteractParamsValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InteractParamsValidationError';\n }\n}\n\nfunction requireNumber(value: unknown, field: string): number {\n if (typeof value !== 'number' || Number.isNaN(value)) {\n throw new InteractParamsValidationError(\n `${field} must be a number for this action`,\n );\n }\n return value;\n}\n\nfunction locateFromPoint(\n x: unknown,\n y: unknown,\n fieldX: string,\n fieldY: string,\n description: string,\n) {\n return generateElementByPoint(\n [\n Math.round(requireNumber(x, fieldX)),\n Math.round(requireNumber(y, fieldY)),\n ],\n description,\n );\n}\n\ntype InteractParamBuilder = (\n body: Record<string, unknown>,\n actionType: string,\n) => Record<string, unknown>;\n\ntype BrowserChromeInteractAction = 'Stop';\n\ntype BrowserChromeInterface = {\n stopLoading?: () => Promise<void>;\n};\n\nconst POINTER_INTERACT_ACTIONS = new Set([\n 'Tap',\n 'DoubleClick',\n 'LongPress',\n 'Swipe',\n 'DragAndDrop',\n 'KeyboardPress',\n 'Input',\n 'Pinch',\n]);\n\nfunction isPointerInteractActionType(actionType: string): boolean {\n return POINTER_INTERACT_ACTIONS.has(actionType);\n}\n\nconst buildLocateActionParams: InteractParamBuilder = (body, actionType) => {\n const params: Record<string, unknown> = {\n locate: locateFromPoint(body.x, body.y, 'x', 'y', `manual ${actionType}`),\n };\n if (typeof body.duration === 'number') {\n params.duration = body.duration;\n }\n return params;\n};\n\nconst buildSwipeParams: InteractParamBuilder = (body) => {\n const params: Record<string, unknown> = {\n start: locateFromPoint(body.x, body.y, 'x', 'y', 'manual swipe start'),\n end: locateFromPoint(\n body.endX,\n body.endY,\n 'endX',\n 'endY',\n 'manual swipe end',\n ),\n };\n if (typeof body.duration === 'number') params.duration = body.duration;\n if (typeof body.repeat === 'number') params.repeat = body.repeat;\n return params;\n};\n\nconst buildDragAndDropParams: InteractParamBuilder = (body) => ({\n from: locateFromPoint(body.x, body.y, 'x', 'y', 'manual drag from'),\n to: locateFromPoint(body.endX, body.endY, 'endX', 'endY', 'manual drag to'),\n});\n\nconst buildKeyboardPressParams: InteractParamBuilder = (body) => {\n if (typeof body.keyName !== 'string') {\n throw new InteractParamsValidationError(\n 'keyName is required for KeyboardPress',\n );\n }\n const params: Record<string, unknown> = { keyName: body.keyName };\n if (typeof body.x === 'number' && typeof body.y === 'number') {\n params.locate = locateFromPoint(\n body.x,\n body.y,\n 'x',\n 'y',\n 'manual keyboard press',\n );\n }\n return params;\n};\n\nconst buildInputParams: InteractParamBuilder = (body) => {\n if (typeof body.value !== 'string') {\n throw new InteractParamsValidationError('value is required for Input');\n }\n const params: Record<string, unknown> = { value: body.value };\n if (typeof body.x === 'number' && typeof body.y === 'number') {\n params.locate = locateFromPoint(body.x, body.y, 'x', 'y', 'manual input');\n }\n if (typeof body.mode === 'string') params.mode = body.mode;\n if (typeof body.autoDismissKeyboard === 'boolean') {\n params.autoDismissKeyboard = body.autoDismissKeyboard;\n }\n return params;\n};\n\nfunction getManualInteractParamBuilder(\n actionType: string,\n): InteractParamBuilder | undefined {\n switch (actionType) {\n case 'Tap':\n case 'DoubleClick':\n case 'RightClick':\n case 'Hover':\n case 'LongPress':\n return buildLocateActionParams;\n case 'Swipe':\n return buildSwipeParams;\n case 'DragAndDrop':\n return buildDragAndDropParams;\n case 'KeyboardPress':\n return buildKeyboardPressParams;\n case 'Input':\n return buildInputParams;\n default:\n return undefined;\n }\n}\n\nexport function buildInteractParams(\n actionType: string,\n body: Record<string, unknown>,\n): Record<string, unknown> {\n const builder = getManualInteractParamBuilder(actionType);\n if (builder) {\n return builder(body, actionType);\n }\n // Fallback: pass-through any caller-provided params for less common actions.\n const { actionType: _omit, ...passthrough } = body as Record<string, unknown>;\n return passthrough;\n}\n\nexport function createManualExecutorContext(\n actionType: string,\n param: unknown,\n): ExecutorContext {\n const task: ExecutionTask = {\n type: 'Action Space',\n subType: actionType,\n param,\n executor: async () => undefined,\n taskId: `manual-${uuid()}`,\n status: 'running',\n };\n return { task };\n}\nconst errorHandler = (\n err: unknown,\n req: Request,\n res: Response,\n next: express.NextFunction,\n) => {\n console.error(err);\n const errorMessage =\n err instanceof Error ? err.message : 'Internal server error';\n res.status(500).json({\n error: errorMessage,\n });\n};\n\ninterface PlaygroundRuntimeState {\n platformId?: string;\n title?: string;\n description?: string;\n preview?: PlaygroundPreviewDescriptor;\n metadata?: Record<string, unknown>;\n}\n\ninterface PlaygroundActiveConnection {\n session: PlaygroundSessionState | null;\n agent: PageAgent | null;\n agentFactory?: AgentFactory | null;\n runtime?: PlaygroundRuntimeState;\n executionHooks?: PlaygroundExecutionHooks;\n sidecars?: PlaygroundSidecar[];\n}\n\nconst RECOVERABLE_PAGE_SESSION_ERROR_PATTERN =\n /Session closed|page has been closed|target closed|browser has been closed|Target page, context or browser has been closed/i;\n\nfunction isRecoverablePageSessionError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return RECOVERABLE_PAGE_SESSION_ERROR_PATTERN.test(message);\n}\n\nclass PlaygroundServer {\n private _app: express.Application;\n tmpDir: string;\n server?: Server;\n port?: number | null;\n staticPath: string;\n taskExecutionDumps: Record<string, ExecutionDump | null>; // Store execution dumps directly\n id: string; // Unique identifier for this server instance\n\n /**\n * Port for scrcpy server (used by Android playground for screen mirroring)\n * When set, this port is injected into the HTML page as window.SCRCPY_PORT\n */\n scrcpyPort?: number;\n\n private _initialized = false;\n\n private readonly _mjpegHandler = new MjpegStreamHandler({\n getNativeUrl: () => this._activeConnection.agent?.interface?.mjpegStreamUrl,\n getActiveInterface: () => this._activeConnection.agent?.interface ?? null,\n takeScreenshot: () =>\n this.getActiveAgentOrThrow().interface.screenshotBase64(),\n canTakeScreenshot: () =>\n typeof this._activeConnection.agent?.interface?.screenshotBase64 ===\n 'function',\n isAgentReady: () => this._agentReady,\n recoverFromPreviewError: async (error, reason) =>\n (await this.recoverActiveAgentAfterPreviewError(error, reason))\n ?.interface ?? null,\n });\n\n private sessionManager?: PlaygroundSessionManager;\n private sessionSetupState: 'required' | 'ready' | 'blocked' = 'ready';\n private sessionSetupBlockingReason?: string;\n\n // Track current running task\n private currentTaskId: string | null = null;\n\n // Flag to pause MJPEG polling during agent recreation or task execution\n private _agentReady = true;\n\n // Flag to track if AI config has changed and agent needs recreation\n private _configDirty = false;\n private _lastAiConfigSignature: string | null = null;\n private _baseRuntimeState?: PlaygroundRuntimeState;\n private _basePreparedMetadata?: Record<string, unknown>;\n private _baseExecutionHooks?: PlaygroundExecutionHooks;\n private _baseSidecars?: PlaygroundSidecar[];\n private _activeConnection: PlaygroundActiveConnection = {\n session: null,\n agent: null,\n agentFactory: null,\n runtime: undefined,\n executionHooks: undefined,\n sidecars: undefined,\n };\n\n private setActiveAgent(\n agent: PageAgent | null,\n options: { preserveActiveStream?: boolean } = {},\n ): void {\n this._activeConnection.agent = agent;\n // The MJPEG hub keys its producer by `activeInterface`. A bare\n // recreateAgent swaps to a new agent instance — even when the\n // underlying device/page is identical — so without a reset the next\n // /mjpeg request finds a stale producer keyed to the previous\n // interface object. `reset()` tears down the producer so the next\n // request rebuilds one. The cancel path opts out: it preserves the\n // browser page across recreates and we want the existing CDP\n // screencast subscribers to keep receiving frames without a\n // disconnect.\n if (!options.preserveActiveStream) {\n this._mjpegHandler.reset();\n }\n }\n\n constructor(\n agent?: PageAgent | (() => PageAgent) | (() => Promise<PageAgent>),\n staticPath = STATIC_PATH,\n id?: string, // Optional override ID\n ) {\n this._app = express();\n this.tmpDir = getTmpDir()!;\n this.staticPath = staticPath;\n this.taskExecutionDumps = {}; // Initialize as empty object\n // Use provided ID, or generate random UUID for each startup\n this.id = id || uuid();\n\n // Support both instance and factory function modes\n if (typeof agent === 'function') {\n this._activeConnection.agentFactory = agent;\n } else {\n this.setActiveAgent(agent || null);\n }\n }\n\n get agent(): PageAgent | null {\n return this._activeConnection.agent;\n }\n\n private assertNoActiveSessionForBaseStateUpdate(methodName: string): void {\n if (this._activeConnection.session) {\n throw new Error(\n `${methodName} cannot update prepared state while a session is active`,\n );\n }\n }\n\n private buildBaseRuntimeState(): PlaygroundRuntimeState | undefined {\n if (!this._baseRuntimeState) {\n return undefined;\n }\n\n return {\n ...this._baseRuntimeState,\n metadata: this.buildSessionMetadata(),\n };\n }\n\n private resetConnectionToBaseState(): void {\n this._activeConnection = {\n session: null,\n agent: this._activeConnection.agent,\n agentFactory: this._activeConnection.agentFactory,\n runtime: this.buildBaseRuntimeState(),\n executionHooks: this._baseExecutionHooks,\n sidecars: this._baseSidecars,\n };\n }\n\n private syncRuntimeState(): void {\n this._baseRuntimeState = {\n ...(this._baseRuntimeState || {}),\n metadata: this.buildSessionMetadata(),\n };\n\n if (this._activeConnection.session) {\n this._activeConnection = {\n ...this._activeConnection,\n runtime: this._activeConnection.runtime\n ? {\n ...this._activeConnection.runtime,\n metadata: this.buildSessionMetadata(),\n }\n : this.buildBaseRuntimeState(),\n };\n return;\n }\n\n this.resetConnectionToBaseState();\n }\n\n private restoreBaseSessionState(): void {\n this.taskExecutionDumps = {};\n this.currentTaskId = null;\n this.sessionSetupState =\n this.sessionSetupState === 'blocked' ? 'blocked' : 'required';\n this._activeConnection = {\n session: null,\n agent: null,\n agentFactory: null,\n runtime: this.buildBaseRuntimeState(),\n executionHooks: this._baseExecutionHooks,\n sidecars: this._baseSidecars,\n };\n this._mjpegHandler.reset();\n this.syncRuntimeState();\n }\n\n setPreparedPlatform(\n prepared: Pick<\n PreparedPlaygroundPlatform,\n | 'platformId'\n | 'title'\n | 'description'\n | 'preview'\n | 'metadata'\n | 'sessionManager'\n | 'executionHooks'\n | 'sidecars'\n >,\n ): void {\n // Allow overriding the initial session created by agentFactory in launch()\n if (this._activeConnection.session && this._activeConnection.agentFactory) {\n this._activeConnection.session = null;\n }\n this.assertNoActiveSessionForBaseStateUpdate('setPreparedPlatform');\n this.sessionManager = prepared.sessionManager;\n this._basePreparedMetadata = prepared.metadata\n ? { ...prepared.metadata }\n : undefined;\n this._baseRuntimeState = {\n platformId: prepared.platformId,\n title: prepared.title,\n description: prepared.description,\n preview: prepared.preview,\n metadata: this.buildSessionMetadata(),\n };\n this._baseExecutionHooks = prepared.executionHooks;\n this._baseSidecars = prepared.sidecars;\n this.resetConnectionToBaseState();\n\n if (\n this.sessionManager &&\n !this._activeConnection.agent &&\n !this._activeConnection.session\n ) {\n this.sessionSetupState =\n this._basePreparedMetadata?.setupState === 'blocked'\n ? 'blocked'\n : 'required';\n this.sessionSetupBlockingReason =\n typeof this._basePreparedMetadata?.setupBlockingReason === 'string'\n ? this._basePreparedMetadata.setupBlockingReason\n : undefined;\n }\n }\n\n setPreviewDescriptor(preview?: PlaygroundPreviewDescriptor): void {\n this.assertNoActiveSessionForBaseStateUpdate('setPreviewDescriptor');\n this._baseRuntimeState = {\n ...(this._baseRuntimeState || {}),\n preview,\n };\n this.resetConnectionToBaseState();\n }\n\n setRuntimeMetadata(metadata?: Record<string, unknown>): void {\n this.assertNoActiveSessionForBaseStateUpdate('setRuntimeMetadata');\n this._basePreparedMetadata = metadata ? { ...metadata } : undefined;\n this.syncRuntimeState();\n }\n\n getRuntimeInfo(): PlaygroundRuntimeInfo {\n return buildRuntimeInfo({\n platformId: this._activeConnection.runtime?.platformId,\n title: this._activeConnection.runtime?.title,\n platformDescription: this._activeConnection.runtime?.description,\n interfaceType:\n this._activeConnection.agent?.interface?.interfaceType || 'Unknown',\n interfaceDescription:\n this._activeConnection.agent?.interface?.describe?.() || undefined,\n preview: this._activeConnection.runtime?.preview,\n metadata: this.buildSessionMetadata(),\n supportsScreenshot:\n typeof this._activeConnection.agent?.interface?.screenshotBase64 ===\n 'function',\n mjpegStreamUrl: this._activeConnection.agent?.interface?.mjpegStreamUrl,\n scrcpyPort: this.scrcpyPort,\n });\n }\n\n getSessionInfo(): PlaygroundSessionState & {\n setupState: 'required' | 'ready' | 'blocked';\n setupBlockingReason?: string;\n } {\n const connected = this.sessionManager\n ? Boolean(\n this._activeConnection.session?.connected &&\n this._activeConnection.agent,\n )\n : Boolean(this._activeConnection.agent);\n\n return {\n connected,\n displayName: this._activeConnection.session?.displayName,\n metadata: {\n ...(this._activeConnection.session?.metadata || {}),\n },\n setupState: this.sessionSetupState,\n setupBlockingReason: this.sessionSetupBlockingReason,\n };\n }\n\n private buildSessionMetadata(): Record<string, unknown> {\n const sessionConnected = this.sessionManager\n ? Boolean(\n this._activeConnection.session?.connected &&\n this._activeConnection.agent,\n )\n : Boolean(this._activeConnection.agent);\n\n return {\n ...(this._basePreparedMetadata || {}),\n ...(this._activeConnection.session?.metadata || {}),\n sessionConnected,\n sessionDisplayName: this._activeConnection.session?.displayName,\n setupState: this.sessionSetupState,\n ...(this.sessionSetupBlockingReason\n ? { setupBlockingReason: this.sessionSetupBlockingReason }\n : {}),\n };\n }\n\n private async startSidecars(sidecars?: PlaygroundSidecar[]): Promise<void> {\n for (const sidecar of sidecars || []) {\n await sidecar.start();\n }\n }\n\n private async stopSidecars(sidecars?: PlaygroundSidecar[]): Promise<void> {\n for (const sidecar of sidecars || []) {\n await sidecar.stop?.();\n }\n }\n\n private getActiveAgentOrThrow(): PageAgent {\n if (!this._activeConnection.agent) {\n throw new Error('No active session');\n }\n\n return this._activeConnection.agent;\n }\n\n private async destroyCurrentAgent({\n preserveActiveStream = false,\n }: { preserveActiveStream?: boolean } = {}): Promise<void> {\n if (!this._activeConnection.agent) {\n return;\n }\n\n try {\n if (typeof this._activeConnection.agent.destroy === 'function') {\n await this._activeConnection.agent.destroy();\n }\n } catch (error) {\n console.warn('Failed to destroy old agent:', error);\n } finally {\n // Forward `preserveActiveStream` so the cancel path doesn't blow\n // away the MJPEG hub on the implicit `setActiveAgent(null)` that\n // happens before `recreateAgent` plugs in the replacement agent.\n this.setActiveAgent(null, { preserveActiveStream });\n // Once the stale agent is gone there is nothing left to recreate.\n this._configDirty = false;\n }\n }\n\n private async destroyCurrentSession(): Promise<void> {\n const previousSession = this._activeConnection.session;\n const previousSidecars = this._activeConnection.sidecars;\n await this.destroyCurrentAgent();\n await this.stopSidecars(previousSidecars);\n\n if (this.sessionManager?.destroySession) {\n await this.sessionManager.destroySession(previousSession || undefined);\n }\n\n this.restoreBaseSessionState();\n }\n\n private async applyCreatedSession(\n session: PlaygroundCreatedSession,\n ): Promise<void> {\n if (!session.agent && !session.agentFactory) {\n throw new Error(\n 'Session creation must provide either an agent or agentFactory',\n );\n }\n\n const sessionSidecars = session.sidecars || this._baseSidecars;\n await this.startSidecars(sessionSidecars);\n\n try {\n this._activeConnection = {\n session: {\n connected: true,\n displayName: session.displayName,\n metadata: session.metadata ? { ...session.metadata } : {},\n },\n agent: session.agent || null,\n agentFactory: session.agentFactory || null,\n runtime: {\n platformId: session.platformId ?? this._baseRuntimeState?.platformId,\n title: session.title ?? this._baseRuntimeState?.title,\n description:\n session.platformDescription ?? this._baseRuntimeState?.description,\n preview: session.preview ?? this._baseRuntimeState?.preview,\n metadata: session.metadata ? { ...session.metadata } : {},\n },\n executionHooks: session.executionHooks || this._baseExecutionHooks,\n sidecars: sessionSidecars,\n };\n this._mjpegHandler.reset();\n this.sessionSetupState = 'ready';\n this.sessionSetupBlockingReason = undefined;\n this.syncRuntimeState();\n } catch (error) {\n await this.stopSidecars(sessionSidecars).catch(() => {});\n this.restoreBaseSessionState();\n throw error;\n }\n }\n\n private async getSessionSetupSchema(\n input?: Record<string, unknown>,\n ): Promise<PlaygroundSessionSetup | null> {\n if (!this.sessionManager) {\n return null;\n }\n\n return this.sessionManager.getSetupSchema\n ? this.sessionManager.getSetupSchema(input)\n : null;\n }\n\n private async getSessionTargets(): Promise<PlaygroundSessionTarget[]> {\n if (!this.sessionManager?.listTargets) {\n return [];\n }\n\n return this.sessionManager.listTargets();\n }\n\n /**\n * Get the Express app instance for custom configuration\n *\n * IMPORTANT: Add middleware (like CORS) BEFORE calling launch()\n * The routes are initialized when launch() is called, so middleware\n * added after launch() will not affect the API routes.\n *\n * @example\n * ```typescript\n * import cors from 'cors';\n *\n * const server = new PlaygroundServer(agent);\n *\n * // Add CORS middleware before launch\n * server.app.use(cors({\n * origin: true,\n * credentials: true,\n * methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']\n * }));\n *\n * await server.launch();\n * ```\n */\n get app(): express.Application {\n return this._app;\n }\n\n /**\n * Initialize Express app with all routes and middleware\n * Called automatically by launch() if not already initialized\n */\n private initializeApp(): void {\n if (this._initialized) return;\n\n // Built-in middleware to parse JSON bodies\n this._app.use(express.json({ limit: '50mb' }));\n\n // Context update middleware (after JSON parsing)\n this._app.use(\n (req: Request, _res: Response, next: express.NextFunction) => {\n const { context } = req.body || {};\n if (\n this._activeConnection.agent &&\n context &&\n 'updateContext' in this._activeConnection.agent.interface &&\n typeof this._activeConnection.agent.interface.updateContext ===\n 'function'\n ) {\n this._activeConnection.agent.interface.updateContext(context);\n console.log('Context updated by PlaygroundServer middleware');\n }\n next();\n },\n );\n\n // NOTE: CORS middleware should be added externally via server.app.use()\n // before calling server.launch() if needed\n\n // API routes\n this.setupRoutes();\n\n // Static file serving (if staticPath is provided)\n this.setupStaticRoutes();\n\n // Error handler middleware (must be last)\n this._app.use(errorHandler);\n\n this._initialized = true;\n }\n\n filePathForUuid(uuid: string) {\n // Validate uuid to prevent path traversal attacks\n // Only allow alphanumeric characters and hyphens\n if (!/^[a-zA-Z0-9-]+$/.test(uuid)) {\n throw new Error('Invalid uuid format');\n }\n const filePath = join(this.tmpDir, `${uuid}.json`);\n // Double-check that resolved path is within tmpDir\n const resolvedPath = resolve(filePath);\n const resolvedTmpDir = resolve(this.tmpDir);\n if (!resolvedPath.startsWith(resolvedTmpDir)) {\n throw new Error('Invalid path');\n }\n return filePath;\n }\n\n saveContextFile(uuid: string, context: string) {\n const tmpFile = this.filePathForUuid(uuid);\n console.log(`save context file: ${tmpFile}`);\n writeFileSync(tmpFile, context);\n return tmpFile;\n }\n\n /**\n * Recreate agent instance (for cancellation).\n *\n * `preserveActiveStream`: skip the MJPEG hub reset so the existing\n * preview stream stays connected across the swap. Safe when the\n * agent factory reuses the same underlying page/browser (Studio Web\n * does this on cancel) — otherwise the producer would point at a\n * dead source.\n */\n private async recreateAgent({\n preserveActiveStream = false,\n }: { preserveActiveStream?: boolean } = {}): Promise<void> {\n this._agentReady = false;\n console.log('Recreating agent to cancel current task...');\n\n await this.destroyCurrentAgent({ preserveActiveStream });\n\n // Create new agent instance if factory is available\n if (this._activeConnection.agentFactory) {\n try {\n this.setActiveAgent(await this._activeConnection.agentFactory(), {\n preserveActiveStream,\n });\n this._agentReady = true;\n console.log('Agent recreated successfully');\n } catch (error) {\n this._agentReady = true;\n console.error('Failed to recreate agent:', error);\n throw error;\n }\n } else {\n this._agentReady = true;\n console.warn(\n 'Agent destroyed but cannot recreate: no factory function provided. Next /execute call will fail.',\n );\n }\n }\n\n private async recoverActiveAgentAfterPreviewError(\n error: unknown,\n reason: string,\n ): Promise<PageAgent | null> {\n if (\n !this._activeConnection.agentFactory ||\n !isRecoverablePageSessionError(error)\n ) {\n return null;\n }\n\n debugMjpeg(`Recovering active agent after ${reason}:`, error);\n try {\n this._mjpegHandler.reset();\n await this.recreateAgent();\n return this._activeConnection.agent;\n } catch (recreateError) {\n debugMjpeg(\n `Failed to recover active agent after ${reason}:`,\n recreateError,\n );\n return null;\n }\n }\n\n private findInteractAction(\n agent: PageAgent,\n actionType: string,\n ): DeviceAction<unknown> | undefined {\n return (agent.interface.actionSpace() as DeviceAction<unknown>[]).find(\n (entry) => entry.name === actionType,\n );\n }\n\n private canRunBrowserChromeInteractAction(\n agent: PageAgent,\n actionType: string,\n ): actionType is BrowserChromeInteractAction {\n return (\n actionType === 'Stop' &&\n typeof (agent.interface as BrowserChromeInterface).stopLoading ===\n 'function'\n );\n }\n\n private async runBrowserChromeInteractAction(\n agent: PageAgent,\n actionType: BrowserChromeInteractAction,\n ): Promise<void> {\n switch (actionType) {\n case 'Stop':\n await (agent.interface as BrowserChromeInterface).stopLoading?.();\n return;\n }\n }\n\n private async runInteractAction(\n agent: PageAgent,\n actionType: string,\n params: Record<string, unknown>,\n ): Promise<void> {\n if (this.canRunBrowserChromeInteractAction(agent, actionType)) {\n await this.runBrowserChromeInteractAction(agent, actionType);\n return;\n }\n\n const action = this.findInteractAction(agent, actionType);\n if (!action || typeof action.call !== 'function') {\n throw new Error(\n `Action \"${actionType}\" is not available on the current device`,\n );\n }\n\n await action.call(params, createManualExecutorContext(actionType, params));\n }\n\n /**\n * Setup all API routes\n */\n private setupRoutes(): void {\n this._app.get('/status', async (req: Request, res: Response) => {\n res.send({\n status: 'ok',\n id: this.id,\n });\n });\n\n this._app.get('/session', async (_req: Request, res: Response) => {\n res.json(this.getSessionInfo());\n });\n\n this._app.get('/session/setup', async (req: Request, res: Response) => {\n try {\n const setup = await this.getSessionSetupSchema(\n Object.fromEntries(\n Object.entries(req.query).filter(\n ([, value]) => typeof value === 'string',\n ),\n ),\n );\n if (!setup) {\n return res.status(404).json({\n error: 'Session setup is not available for this playground',\n });\n }\n\n const targets = await this.getSessionTargets();\n res.json({\n ...setup,\n targets: targets.length > 0 ? targets : setup.targets,\n });\n } catch (error) {\n res.status(500).json({\n error:\n error instanceof Error\n ? error.message\n : 'Failed to load session setup',\n });\n }\n });\n\n this._app.get('/session/targets', async (_req: Request, res: Response) => {\n try {\n res.json(await this.getSessionTargets());\n } catch (error) {\n res.status(500).json({\n error:\n error instanceof Error\n ? error.message\n : 'Failed to load session targets',\n });\n }\n });\n\n this._app.post('/session', async (req: Request, res: Response) => {\n if (!this.sessionManager) {\n return res.status(404).json({\n error: 'Session creation is not available for this playground',\n });\n }\n\n if (this.currentTaskId) {\n return res.status(409).json({\n error: 'Cannot replace session while a task is running',\n });\n }\n\n try {\n await this.destroyCurrentSession();\n const created = await this.sessionManager.createSession(req.body || {});\n await this.applyCreatedSession(created);\n\n if (\n !this._activeConnection.agent &&\n this._activeConnection.agentFactory\n ) {\n this.setActiveAgent(await this._activeConnection.agentFactory());\n }\n\n if (this._configDirty && this._activeConnection.agentFactory) {\n this._configDirty = false;\n await this.recreateAgent();\n }\n\n res.json({\n session: this.getSessionInfo(),\n runtimeInfo: this.getRuntimeInfo(),\n });\n } catch (error) {\n const failedSessionSidecars = this._activeConnection.session\n ? this._activeConnection.sidecars\n : undefined;\n await this.destroyCurrentAgent();\n await this.stopSidecars(failedSessionSidecars).catch(() => {});\n this.restoreBaseSessionState();\n res.status(400).json({\n error:\n error instanceof Error ? error.message : 'Failed to create session',\n });\n }\n });\n\n this._app.delete('/session', async (_req: Request, res: Response) => {\n if (this.currentTaskId) {\n return res.status(409).json({\n error: 'Cannot destroy session while a task is running',\n });\n }\n\n try {\n await this.destroyCurrentSession();\n res.json({\n session: this.getSessionInfo(),\n runtimeInfo: this.getRuntimeInfo(),\n });\n } catch (error) {\n res.status(500).json({\n error:\n error instanceof Error\n ? error.message\n : 'Failed to destroy session',\n });\n }\n });\n\n this._app.get('/context/:uuid', async (req: Request, res: Response) => {\n const { uuid } = req.params;\n let contextFile: string;\n try {\n contextFile = this.filePathForUuid(uuid);\n } catch {\n return res.status(400).json({\n error: 'Invalid uuid format',\n });\n }\n\n if (!existsSync(contextFile)) {\n return res.status(404).json({\n error: 'Context not found',\n });\n }\n\n const context = readFileSync(contextFile, 'utf8');\n res.json({\n context,\n });\n });\n\n this._app.get(\n '/task-progress/:requestId',\n async (req: Request, res: Response) => {\n const { requestId } = req.params;\n const executionDump = this.taskExecutionDumps[requestId] || null;\n\n res.json({\n executionDump,\n });\n },\n );\n\n this._app.post('/action-space', async (req: Request, res: Response) => {\n try {\n const agent = this.getActiveAgentOrThrow();\n let actionSpace = [];\n\n actionSpace = agent.interface.actionSpace();\n\n // Process actionSpace to make paramSchema serializable with shape info\n const processedActionSpace = actionSpace.map((action: unknown) => {\n if (action && typeof action === 'object' && 'paramSchema' in action) {\n const typedAction = action as {\n paramSchema?: { shape?: object; [key: string]: unknown };\n [key: string]: unknown;\n };\n if (\n typedAction.paramSchema &&\n typeof typedAction.paramSchema === 'object'\n ) {\n // Extract shape information from Zod schema\n let processedSchema = null;\n\n try {\n // Extract shape from runtime Zod object\n if (\n typedAction.paramSchema.shape &&\n typeof typedAction.paramSchema.shape === 'object'\n ) {\n const rawShape = typedAction.paramSchema.shape as Record<\n string,\n any\n >;\n const serializedShape: Record<string, any> = {};\n for (const [key, field] of Object.entries(rawShape)) {\n serializedShape[key] = serializeZodField(field);\n }\n processedSchema = {\n type: 'ZodObject',\n shape: serializedShape,\n };\n }\n } catch (e) {\n const actionName =\n 'name' in typedAction && typeof typedAction.name === 'string'\n ? typedAction.name\n : 'unknown';\n console.warn(\n 'Failed to process paramSchema for action:',\n actionName,\n e,\n );\n }\n\n return {\n ...typedAction,\n paramSchema: processedSchema,\n };\n }\n }\n return action;\n });\n\n res.json(processedActionSpace);\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error('Failed to get action space:', error);\n res.status(errorMessage === 'No active session' ? 409 : 500).json({\n error: errorMessage,\n });\n }\n });\n\n // -------------------------\n // actions from report file\n this._app.post(\n '/playground-with-context',\n async (req: Request, res: Response) => {\n const context = req.body.context;\n\n if (!context) {\n return res.status(400).json({\n error: 'context is required',\n });\n }\n\n const requestId = uuid();\n this.saveContextFile(requestId, context);\n return res.json({\n location: `/playground/${requestId}`,\n uuid: requestId,\n });\n },\n );\n\n this._app.post('/execute', async (req: Request, res: Response) => {\n let agent: PageAgent;\n try {\n agent = this.getActiveAgentOrThrow();\n } catch (error) {\n return res.status(409).json({\n error: error instanceof Error ? error.message : 'No active session',\n });\n }\n\n const {\n type,\n prompt,\n params,\n requestId,\n deepLocate,\n deepThink,\n screenshotIncluded,\n domIncluded,\n deviceOptions,\n } = req.body;\n\n if (!type) {\n return res.status(400).json({\n error: 'type is required',\n });\n }\n\n // Recreate agent only when AI config has changed (via /config API)\n if (this._activeConnection.agentFactory && this._configDirty) {\n this._configDirty = false;\n this._agentReady = false;\n console.log('AI config changed, recreating agent...');\n try {\n await this.destroyCurrentAgent();\n this.setActiveAgent(await this._activeConnection.agentFactory());\n agent = this.getActiveAgentOrThrow();\n this._agentReady = true;\n console.log('Agent recreated with new config');\n } catch (error) {\n this._agentReady = true;\n console.error('Failed to recreate agent:', error);\n return res.status(500).json({\n error: `Failed to create agent: ${error instanceof Error ? error.message : 'Unknown error'}`,\n });\n }\n }\n\n // Update device options if provided\n if (deviceOptions) {\n const iface = agent.interface as unknown as {\n options?: Record<string, unknown>;\n };\n iface.options = {\n ...(iface.options || {}),\n ...deviceOptions,\n };\n }\n\n // Check if another task is running\n if (this.currentTaskId) {\n return res.status(409).json({\n error: 'Another task is already running',\n currentTaskId: this.currentTaskId,\n });\n }\n\n // Lock this task\n if (requestId) {\n this.currentTaskId = requestId;\n this.taskExecutionDumps[requestId] = null;\n\n // Use onDumpUpdate to receive and store executionDump directly\n agent.onDumpUpdate = (_dump: string, executionDump?: ExecutionDump) => {\n if (executionDump) {\n // Store the execution dump directly without transformation\n this.taskExecutionDumps[requestId] = executionDump;\n }\n };\n }\n\n const response: {\n result: unknown;\n dump: ExecutionDump | null;\n error: string | null;\n reportHTML: string | null;\n requestId?: string;\n } = {\n result: null,\n dump: null,\n error: null,\n reportHTML: null,\n requestId,\n };\n\n const startTime = Date.now();\n try {\n await this._activeConnection.executionHooks?.beforeExecute?.();\n\n // Get action space to check for dynamic actions\n const actionSpace = agent.interface.actionSpace();\n\n // Prepare value object for executeAction\n const value = {\n type,\n prompt,\n params,\n };\n\n response.result = await executeAction(agent, type, actionSpace, value, {\n deepLocate,\n deepThink,\n screenshotIncluded,\n domIncluded,\n deviceOptions,\n });\n } catch (error: unknown) {\n response.error = formatErrorMessage(error);\n } finally {\n try {\n await this._activeConnection.executionHooks?.afterExecute?.();\n } catch (hookError) {\n console.error('Failed to run execution after hook:', hookError);\n }\n }\n\n try {\n const dumpString = agent.dumpDataString({\n inlineScreenshots: true,\n });\n if (dumpString) {\n const groupedDump = ReportActionDump.fromSerializedString(dumpString);\n // Extract first execution from grouped dump, matching local execution adapter behavior\n response.dump = groupedDump.executions?.[0] || null;\n } else {\n response.dump = null;\n }\n response.reportHTML =\n agent.reportHTMLString({ inlineScreenshots: true }) || null;\n\n agent.writeOutActionDumps();\n agent.resetDump();\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(\n `write out dump failed: requestId: ${requestId}, ${errorMessage}`,\n );\n } finally {\n }\n\n res.send(response);\n const timeCost = Date.now() - startTime;\n\n if (response.error) {\n console.error(\n `handle request failed after ${timeCost}ms: requestId: ${requestId}, ${response.error}`,\n );\n } else {\n console.log(\n `handle request done after ${timeCost}ms: requestId: ${requestId}`,\n );\n }\n\n // Clean up task execution dumps and unlock after execution completes\n if (requestId) {\n delete this.taskExecutionDumps[requestId];\n // Release the lock\n if (this.currentTaskId === requestId) {\n this.currentTaskId = null;\n }\n }\n });\n\n this._app.post(\n '/cancel/:requestId',\n async (req: Request, res: Response) => {\n const { requestId } = req.params;\n\n if (!requestId) {\n return res.status(400).json({\n error: 'requestId is required',\n });\n }\n\n try {\n const agent = this.getActiveAgentOrThrow();\n // Check if this is the current running task\n if (this.currentTaskId !== requestId) {\n return res.json({\n status: 'not_found',\n message: 'Task not found or already completed',\n });\n }\n\n console.log(`Cancelling task: ${requestId}`);\n\n // Get current execution data before cancelling (dump and reportHTML)\n let dump: any = null;\n let reportHTML: string | null = null;\n\n try {\n const dumpString = agent.dumpDataString?.({\n inlineScreenshots: true,\n });\n if (dumpString) {\n const groupedDump =\n ReportActionDump.fromSerializedString(dumpString);\n // Extract first execution from grouped dump\n dump = groupedDump.executions?.[0] || null;\n }\n\n reportHTML =\n agent.reportHTMLString?.({\n inlineScreenshots: true,\n }) || null;\n } catch (error: unknown) {\n console.warn('Failed to get execution data before cancel:', error);\n }\n\n // Destroy and recreate agent to cancel the current task,\n // while keeping the live preview stream alive so the user\n // doesn't see a 3–5s blackout / page reload when they hit\n // Stop. Platform factories that reuse the same device or\n // page across recreates (e.g. Studio Web) honor this hint.\n try {\n await this.recreateAgent({ preserveActiveStream: true });\n } catch (error) {\n console.warn('Failed to recreate agent during cancel:', error);\n }\n\n // Clean up\n delete this.taskExecutionDumps[requestId];\n this.currentTaskId = null;\n\n res.json({\n status: 'cancelled',\n message: 'Task cancelled successfully',\n dump,\n reportHTML,\n });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to cancel: ${errorMessage}`);\n res.status(errorMessage === 'No active session' ? 409 : 500).json({\n error: `Failed to cancel: ${errorMessage}`,\n });\n }\n },\n );\n\n // Screenshot API for real-time screenshot polling\n this._app.get('/screenshot', async (_req: Request, res: Response) => {\n try {\n let agent = this.getActiveAgentOrThrow();\n // Check if page has screenshotBase64 method\n if (typeof agent.interface.screenshotBase64 !== 'function') {\n return res.status(500).json({\n error: 'Screenshot method not available on current interface',\n });\n }\n\n let screenshot: string;\n try {\n screenshot = await agent.interface.screenshotBase64();\n } catch (error) {\n const recoveredAgent = await this.recoverActiveAgentAfterPreviewError(\n error,\n 'screenshot capture',\n );\n if (\n !recoveredAgent ||\n typeof recoveredAgent.interface.screenshotBase64 !== 'function'\n ) {\n throw error;\n }\n agent = recoveredAgent;\n screenshot = await agent.interface.screenshotBase64();\n }\n\n res.json({\n screenshot,\n timestamp: Date.now(),\n });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n const statusCode = errorMessage === 'No active session' ? 409 : 500;\n if (statusCode !== 409) {\n console.error(`Failed to take screenshot: ${errorMessage}`);\n }\n res.status(statusCode).json({\n error: `Failed to take screenshot: ${errorMessage}`,\n });\n }\n });\n\n // MJPEG streaming endpoint for real-time screen preview. The actual\n // probe / proxy / in-process producer / polling logic lives in\n // MjpegStreamHandler so this route is just HTTP plumbing.\n this._app.get('/mjpeg', async (req: Request, res: Response) => {\n const agent = this._activeConnection.agent;\n if (!agent) {\n return res.status(409).json({ error: 'No active session' });\n }\n await this._mjpegHandler.serve(req, res);\n });\n\n // Interface info API for getting interface type and description\n this._app.get('/interface-info', async (_req: Request, res: Response) => {\n try {\n const runtimeInfo = this.getRuntimeInfo();\n const agent = this._activeConnection.agent;\n let size: { width: number; height: number } | undefined;\n let navigationState: { isLoading: boolean } | undefined;\n let actionTypes: string[] | undefined;\n if (typeof agent?.interface?.size === 'function') {\n try {\n size = await agent.interface.size();\n } catch (error) {\n debugScreenshot('interface size() failed:', error);\n }\n }\n if (typeof agent?.interface?.navigationState === 'function') {\n try {\n navigationState = await agent.interface.navigationState();\n } catch (error) {\n debugScreenshot('interface navigationState() failed:', error);\n }\n }\n if (typeof agent?.interface?.actionSpace === 'function') {\n try {\n const actions = agent.interface.actionSpace();\n actionTypes = Array.isArray(actions)\n ? actions\n .map((action) => action?.name)\n .filter((name): name is string => typeof name === 'string')\n : undefined;\n } catch (error) {\n debugScreenshot('interface actionSpace() failed:', error);\n }\n }\n\n res.json({\n type: runtimeInfo.interface.type,\n description: runtimeInfo.interface.description,\n ...(size ? { size } : {}),\n ...(navigationState ? { navigationState } : {}),\n ...(actionTypes ? { actionTypes } : {}),\n });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to get interface info: ${errorMessage}`);\n res.status(500).json({\n error: `Failed to get interface info: ${errorMessage}`,\n });\n }\n });\n\n // Direct manipulation API – invokes a named action immediately, bypassing\n // AI planning, the task lock, and dump bookkeeping. Primitive-capable\n // device previews use the typed input surface; browser navigation falls\n // back to explicit actionSpace/browser-chrome actions.\n this._app.post('/interact', async (req: Request, res: Response) => {\n let agent: PageAgent;\n try {\n agent = this.getActiveAgentOrThrow();\n } catch (error) {\n return res.status(409).json({\n error: error instanceof Error ? error.message : 'No active session',\n });\n }\n\n const { actionType } = req.body ?? {};\n if (typeof actionType !== 'string' || !actionType) {\n return res.status(400).json({\n error: 'actionType is required',\n });\n }\n\n try {\n const inputPrimitives = agent.interface.inputPrimitives;\n if (inputPrimitives) {\n await dispatchPointer(inputPrimitives, req.body ?? {}, () =>\n agent.interface.size(),\n );\n res.json({});\n return;\n }\n\n if (\n !this.findInteractAction(agent, actionType) &&\n !this.canRunBrowserChromeInteractAction(agent, actionType)\n ) {\n return res.status(404).json({\n error: isPointerInteractActionType(actionType)\n ? 'Manual control is not supported on this device'\n : `Action \"${actionType}\" is not available on the current device`,\n });\n }\n\n const params = buildInteractParams(actionType, req.body ?? {});\n await this.runInteractAction(agent, actionType, params);\n res.json({});\n } catch (error: unknown) {\n if (error instanceof PointerInputError) {\n return res.status(error.statusCode).json({ error: error.message });\n }\n if (error instanceof InteractParamsValidationError) {\n return res.status(400).json({ error: error.message });\n }\n\n const recoveredAgent = await this.recoverActiveAgentAfterPreviewError(\n error,\n `manual interact action \"${actionType}\"`,\n );\n if (recoveredAgent) {\n return res.status(409).json({\n error:\n 'The page session was closed and has been recreated. Please retry the action.',\n });\n }\n\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(\n `Failed to run interact action \"${actionType}\": ${errorMessage}`,\n );\n res.status(500).json({ error: errorMessage });\n }\n });\n\n this._app.get('/runtime-info', async (_req: Request, res: Response) => {\n try {\n res.json(this.getRuntimeInfo());\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to get runtime info: ${errorMessage}`);\n res.status(500).json({\n error: `Failed to get runtime info: ${errorMessage}`,\n });\n }\n });\n\n this.app.post('/config', async (req: Request, res: Response) => {\n const { aiConfig } = req.body;\n\n if (!aiConfig || typeof aiConfig !== 'object') {\n return res.status(400).json({\n error: 'aiConfig is required and must be an object',\n });\n }\n\n if (Object.keys(aiConfig).length === 0) {\n return res.json({\n status: 'ok',\n message: 'AI config not changed due to empty object',\n });\n }\n\n const nextConfigSignature = serializeAiConfigSignature(aiConfig);\n const configChanged = nextConfigSignature !== this._lastAiConfigSignature;\n\n try {\n if (configChanged) {\n overrideAIConfig(aiConfig);\n this._lastAiConfigSignature = nextConfigSignature;\n this._configDirty = Boolean(this._activeConnection.agent);\n }\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to update AI config: ${errorMessage}`);\n return res.status(500).json({\n error: `Failed to update AI config: ${errorMessage}`,\n });\n }\n\n if (!configChanged) {\n return res.json({\n status: 'ok',\n message: 'AI config not changed because it is identical to current',\n });\n }\n\n // Validate the config immediately so the frontend gets early feedback\n try {\n globalModelConfigManager.getModelConfig('default');\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`AI config validation failed: ${errorMessage}`);\n return res.status(400).json({\n error: errorMessage,\n });\n }\n\n return res.json({\n status: 'ok',\n message: this._configDirty\n ? 'AI config updated. Agent will be recreated on next execution.'\n : 'AI config updated. New sessions will use it immediately.',\n });\n });\n\n this.app.post(\n '/connectivity-test',\n async (_req: Request, res: Response) => {\n try {\n const result = await runConnectivityTest({\n defaultModelConfig:\n globalModelConfigManager.getModelConfig('default'),\n planningModelConfig:\n globalModelConfigManager.getModelConfig('planning'),\n insightModelConfig:\n globalModelConfigManager.getModelConfig('insight'),\n });\n return res.json(result);\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Connectivity test failed: ${errorMessage}`);\n return res.status(500).json({\n error: errorMessage,\n });\n }\n },\n );\n }\n\n /**\n * Setup static file serving routes\n */\n private setupStaticRoutes(): void {\n // Handle index.html with port injection\n this._app.get('/', (_req: Request, res: Response) => {\n this.serveHtmlWithPorts(res);\n });\n\n this._app.get('/index.html', (_req: Request, res: Response) => {\n this.serveHtmlWithPorts(res);\n });\n\n // Use express.static middleware for secure static file serving\n this._app.use(express.static(this.staticPath));\n\n // Fallback to index.html for SPA routing\n this._app.get('*', (_req: Request, res: Response) => {\n this.serveHtmlWithPorts(res);\n });\n }\n\n /**\n * Serve HTML with injected port configuration\n */\n private serveHtmlWithPorts(res: Response): void {\n try {\n const htmlPath = join(this.staticPath, 'index.html');\n let html = readFileSync(htmlPath, 'utf8');\n\n const scrcpyPort = this.scrcpyPort ?? this.port! + 1;\n\n // Inject scrcpy port configuration script into HTML head\n const configScript = `\n <script>\n window.SCRCPY_PORT = ${scrcpyPort};\n </script>\n `;\n\n // Insert the script before closing </head> tag\n html = html.replace('</head>', `${configScript}</head>`);\n\n res.setHeader('Content-Type', 'text/html');\n res.send(html);\n } catch (error) {\n console.error('Error serving HTML with ports:', error);\n res.status(500).send('Internal Server Error');\n }\n }\n\n /**\n * Launch the server on specified port\n */\n async launch(port?: number): Promise<PlaygroundServer> {\n // If using factory mode, initialize agent\n if (this._activeConnection.agentFactory && !this.sessionManager) {\n console.log('Initializing agent from factory function...');\n this.setActiveAgent(await this._activeConnection.agentFactory());\n this._activeConnection.session = {\n connected: true,\n metadata: {},\n };\n this.sessionSetupState = 'ready';\n this.syncRuntimeState();\n console.log('Agent initialized successfully');\n }\n\n // Initialize routes now, after any middleware has been added\n this.initializeApp();\n\n this.port = port || defaultPort;\n\n return new Promise((resolve) => {\n const serverPort = this.port ?? defaultPort;\n this.server = this._app.listen(serverPort, '0.0.0.0', () => {\n resolve(this);\n });\n });\n }\n\n /**\n * Close the server and clean up resources\n */\n async close(): Promise<void> {\n await this.destroyCurrentSession().catch((error) => {\n console.warn('Failed to destroy current session during shutdown:', error);\n });\n this._mjpegHandler.shutdown();\n\n return new Promise((resolve, reject) => {\n if (this.server) {\n this.taskExecutionDumps = {};\n\n // Close the server\n this.server.close((error) => {\n if (error) {\n reject(error);\n } else {\n this.server = undefined;\n resolve();\n }\n });\n } else {\n resolve();\n }\n });\n }\n}\n\nexport default PlaygroundServer;\nexport { PlaygroundServer };\n"],"names":["defaultPort","PLAYGROUND_SERVER_PORT","serializeAiConfigSignature","aiConfig","JSON","Object","leftKey","rightKey","serializeZodField","field","def","typeName","result","Array","rawShape","serializedShape","k","v","__filename","fileURLToPath","__dirname","dirname","STATIC_PATH","join","debugScreenshot","getDebug","debugMjpeg","InteractParamsValidationError","Error","message","requireNumber","value","Number","locateFromPoint","x","y","fieldX","fieldY","description","generateElementByPoint","Math","POINTER_INTERACT_ACTIONS","Set","isPointerInteractActionType","actionType","buildLocateActionParams","body","params","buildSwipeParams","buildDragAndDropParams","buildKeyboardPressParams","buildInputParams","getManualInteractParamBuilder","buildInteractParams","builder","_omit","passthrough","createManualExecutorContext","param","task","undefined","uuid","errorHandler","err","req","res","next","console","errorMessage","RECOVERABLE_PAGE_SESSION_ERROR_PATTERN","isRecoverablePageSessionError","error","String","PlaygroundServer","agent","options","methodName","prepared","preview","metadata","buildRuntimeInfo","connected","Boolean","sessionConnected","sidecars","sidecar","preserveActiveStream","previousSession","previousSidecars","session","sessionSidecars","input","express","_res","context","filePath","resolvedPath","resolve","resolvedTmpDir","tmpFile","writeFileSync","reason","recreateError","entry","action","_req","setup","targets","created","failedSessionSidecars","contextFile","existsSync","readFileSync","requestId","executionDump","actionSpace","processedActionSpace","typedAction","processedSchema","key","e","actionName","type","prompt","deepLocate","deepThink","screenshotIncluded","domIncluded","deviceOptions","iface","_dump","response","startTime","Date","executeAction","formatErrorMessage","hookError","dumpString","groupedDump","ReportActionDump","timeCost","dump","reportHTML","screenshot","recoveredAgent","statusCode","runtimeInfo","size","navigationState","actionTypes","actions","name","inputPrimitives","dispatchPointer","PointerInputError","nextConfigSignature","configChanged","overrideAIConfig","globalModelConfigManager","runConnectivityTest","htmlPath","html","scrcpyPort","configScript","port","Promise","serverPort","reject","staticPath","id","MjpegStreamHandler","getTmpDir"],"mappings":"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"}
1
+ {"version":3,"file":"server.mjs","sources":["../../src/server.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport type { Server } from 'node:http';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type {\n DeviceAction,\n ExecutionDump,\n ExecutionTask,\n ExecutorContext,\n} from '@midscene/core';\nimport { ReportActionDump, runConnectivityTest } from '@midscene/core';\nimport type { Agent as PageAgent } from '@midscene/core/agent';\nimport { getTmpDir } from '@midscene/core/utils';\nimport { PLAYGROUND_SERVER_PORT } from '@midscene/shared/constants';\nimport {\n globalModelConfigManager,\n overrideAIConfig,\n} from '@midscene/shared/env';\nimport { generateElementByPoint } from '@midscene/shared/extractor';\nimport { getDebug } from '@midscene/shared/logger';\nimport { uuid } from '@midscene/shared/utils';\nimport express, { type Request, type Response } from 'express';\nimport { executeAction, formatErrorMessage } from './common';\nimport { MjpegStreamHandler } from './mjpeg-stream-handler';\nimport type {\n PlaygroundCreatedSession,\n PlaygroundExecutionHooks,\n PlaygroundPreviewDescriptor,\n PlaygroundSessionManager,\n PlaygroundSessionSetup,\n PlaygroundSessionState,\n PlaygroundSessionTarget,\n PlaygroundSidecar,\n PreparedPlaygroundPlatform,\n} from './platform';\nimport { PointerInputError, dispatchPointer } from './pointer-dispatch';\nimport {\n type PlaygroundRuntimeInfo,\n buildRuntimeInfo,\n} from './runtime-metadata';\nimport type { AgentFactory } from './types';\n\nimport 'dotenv/config';\n\nconst defaultPort = PLAYGROUND_SERVER_PORT;\n\nfunction serializeAiConfigSignature(aiConfig: Record<string, unknown>): string {\n return JSON.stringify(\n Object.entries(aiConfig).sort(([leftKey], [rightKey]) =>\n leftKey.localeCompare(rightKey),\n ),\n );\n}\n\n/**\n * Recursively serialize a Zod field into a plain object that preserves\n * the `_def` metadata the client relies on (typeName, innerType, values,\n * defaultValue, description, shape, etc.).\n */\nexport function serializeZodField(field: any): any {\n if (!field || typeof field !== 'object') return field;\n\n const def = field._def;\n if (!def || typeof def !== 'object') return field;\n\n const typeName: string | undefined = def.typeName;\n\n const result: Record<string, any> = {\n _def: {\n typeName,\n },\n };\n\n // Preserve description\n if (def.description) {\n result._def.description = def.description;\n }\n\n // Wrapper types (ZodOptional, ZodDefault, ZodNullable) – recurse into innerType\n if (def.innerType) {\n result._def.innerType = serializeZodField(def.innerType);\n }\n\n // ZodDefault – preserve defaultValue as a serializable plain value\n if (typeName === 'ZodDefault' && typeof def.defaultValue === 'function') {\n try {\n result._def._serializedDefaultValue = def.defaultValue();\n } catch {\n // ignore\n }\n }\n\n // ZodEnum – preserve values array\n if (typeName === 'ZodEnum' && Array.isArray(def.values)) {\n result._def.values = def.values;\n }\n\n // ZodObject – recurse into shape\n if (typeName === 'ZodObject') {\n const rawShape = typeof def.shape === 'function' ? def.shape() : def.shape;\n if (rawShape && typeof rawShape === 'object') {\n const serializedShape: Record<string, any> = {};\n for (const [k, v] of Object.entries(rawShape)) {\n serializedShape[k] = serializeZodField(v);\n }\n result._def.shape = serializedShape;\n result.shape = serializedShape;\n }\n }\n\n // Copy top-level description for compatibility\n if (field.description) {\n result.description = field.description;\n }\n\n return result;\n}\n\n// Static path for playground files\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst STATIC_PATH = join(__dirname, '..', '..', 'static');\n\nconst debugScreenshot = getDebug('playground:screenshot', { console: true });\nconst debugMjpeg = getDebug('playground:mjpeg', { console: true });\n\n/**\n * Thrown when a caller supplies an /interact body that fails validation\n * (missing x/y, missing keyName for KeyboardPress, etc.). Distinct from a\n * downstream device failure so the route handler can map this to HTTP 400.\n */\nexport class InteractParamsValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InteractParamsValidationError';\n }\n}\n\nfunction requireNumber(value: unknown, field: string): number {\n if (typeof value !== 'number' || Number.isNaN(value)) {\n throw new InteractParamsValidationError(\n `${field} must be a number for this action`,\n );\n }\n return value;\n}\n\nfunction locateFromPoint(\n x: unknown,\n y: unknown,\n fieldX: string,\n fieldY: string,\n description: string,\n) {\n return generateElementByPoint(\n [\n Math.round(requireNumber(x, fieldX)),\n Math.round(requireNumber(y, fieldY)),\n ],\n description,\n );\n}\n\ntype InteractParamBuilder = (\n body: Record<string, unknown>,\n actionType: string,\n) => Record<string, unknown>;\n\ntype BrowserChromeInteractAction = 'Stop';\n\ntype BrowserChromeInterface = {\n stopLoading?: () => Promise<void>;\n};\n\nconst POINTER_INTERACT_ACTIONS = new Set([\n 'Tap',\n 'DoubleClick',\n 'LongPress',\n 'Swipe',\n 'DragAndDrop',\n 'KeyboardPress',\n 'Input',\n 'Pinch',\n]);\n\nfunction isPointerInteractActionType(actionType: string): boolean {\n return POINTER_INTERACT_ACTIONS.has(actionType);\n}\n\nconst buildLocateActionParams: InteractParamBuilder = (body, actionType) => {\n const params: Record<string, unknown> = {\n locate: locateFromPoint(body.x, body.y, 'x', 'y', `manual ${actionType}`),\n };\n if (typeof body.duration === 'number') {\n params.duration = body.duration;\n }\n return params;\n};\n\nconst buildSwipeParams: InteractParamBuilder = (body) => {\n const params: Record<string, unknown> = {\n start: locateFromPoint(body.x, body.y, 'x', 'y', 'manual swipe start'),\n end: locateFromPoint(\n body.endX,\n body.endY,\n 'endX',\n 'endY',\n 'manual swipe end',\n ),\n };\n if (typeof body.duration === 'number') params.duration = body.duration;\n if (typeof body.repeat === 'number') params.repeat = body.repeat;\n return params;\n};\n\nconst buildDragAndDropParams: InteractParamBuilder = (body) => ({\n from: locateFromPoint(body.x, body.y, 'x', 'y', 'manual drag from'),\n to: locateFromPoint(body.endX, body.endY, 'endX', 'endY', 'manual drag to'),\n});\n\nconst buildKeyboardPressParams: InteractParamBuilder = (body) => {\n if (typeof body.keyName !== 'string') {\n throw new InteractParamsValidationError(\n 'keyName is required for KeyboardPress',\n );\n }\n const params: Record<string, unknown> = { keyName: body.keyName };\n if (typeof body.x === 'number' && typeof body.y === 'number') {\n params.locate = locateFromPoint(\n body.x,\n body.y,\n 'x',\n 'y',\n 'manual keyboard press',\n );\n }\n return params;\n};\n\nconst buildInputParams: InteractParamBuilder = (body) => {\n if (typeof body.value !== 'string') {\n throw new InteractParamsValidationError('value is required for Input');\n }\n const params: Record<string, unknown> = { value: body.value };\n if (typeof body.x === 'number' && typeof body.y === 'number') {\n params.locate = locateFromPoint(body.x, body.y, 'x', 'y', 'manual input');\n }\n if (typeof body.mode === 'string') params.mode = body.mode;\n if (typeof body.autoDismissKeyboard === 'boolean') {\n params.autoDismissKeyboard = body.autoDismissKeyboard;\n }\n return params;\n};\n\nfunction getManualInteractParamBuilder(\n actionType: string,\n): InteractParamBuilder | undefined {\n switch (actionType) {\n case 'Tap':\n case 'DoubleClick':\n case 'RightClick':\n case 'Hover':\n case 'LongPress':\n return buildLocateActionParams;\n case 'Swipe':\n return buildSwipeParams;\n case 'DragAndDrop':\n return buildDragAndDropParams;\n case 'KeyboardPress':\n return buildKeyboardPressParams;\n case 'Input':\n return buildInputParams;\n default:\n return undefined;\n }\n}\n\nexport function buildInteractParams(\n actionType: string,\n body: Record<string, unknown>,\n): Record<string, unknown> {\n const builder = getManualInteractParamBuilder(actionType);\n if (builder) {\n return builder(body, actionType);\n }\n // Fallback: pass-through any caller-provided params for less common actions.\n const { actionType: _omit, ...passthrough } = body as Record<string, unknown>;\n return passthrough;\n}\n\nexport function createManualExecutorContext(\n actionType: string,\n param: unknown,\n): ExecutorContext {\n const task: ExecutionTask = {\n type: 'Action Space',\n subType: actionType,\n param,\n executor: async () => undefined,\n taskId: `manual-${uuid()}`,\n status: 'running',\n };\n return { task };\n}\nconst errorHandler = (\n err: unknown,\n req: Request,\n res: Response,\n next: express.NextFunction,\n) => {\n console.error(err);\n const errorMessage =\n err instanceof Error ? err.message : 'Internal server error';\n res.status(500).json({\n error: errorMessage,\n });\n};\n\ninterface PlaygroundRuntimeState {\n platformId?: string;\n title?: string;\n description?: string;\n preview?: PlaygroundPreviewDescriptor;\n metadata?: Record<string, unknown>;\n}\n\ninterface PlaygroundActiveConnection {\n session: PlaygroundSessionState | null;\n agent: PageAgent | null;\n agentFactory?: AgentFactory | null;\n runtime?: PlaygroundRuntimeState;\n executionHooks?: PlaygroundExecutionHooks;\n sidecars?: PlaygroundSidecar[];\n}\n\nconst RECOVERABLE_PAGE_SESSION_ERROR_PATTERN =\n /Session closed|page has been closed|target closed|browser has been closed|Target page, context or browser has been closed/i;\n\nfunction isRecoverablePageSessionError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return RECOVERABLE_PAGE_SESSION_ERROR_PATTERN.test(message);\n}\n\nclass PlaygroundServer {\n private _app: express.Application;\n tmpDir: string;\n server?: Server;\n port?: number | null;\n staticPath: string;\n taskExecutionDumps: Record<string, ExecutionDump | null>; // Store execution dumps directly\n id: string; // Unique identifier for this server instance\n\n /**\n * Port for scrcpy server (used by Android playground for screen mirroring)\n * When set, this port is injected into the HTML page as window.SCRCPY_PORT\n */\n scrcpyPort?: number;\n\n private _initialized = false;\n\n private readonly _mjpegHandler = new MjpegStreamHandler({\n getNativeUrl: () => this._activeConnection.agent?.interface?.mjpegStreamUrl,\n getActiveInterface: () => this._activeConnection.agent?.interface ?? null,\n takeScreenshot: () =>\n this.getActiveAgentOrThrow().interface.screenshotBase64(),\n canTakeScreenshot: () =>\n typeof this._activeConnection.agent?.interface?.screenshotBase64 ===\n 'function',\n isAgentReady: () => this._agentReady,\n recoverFromPreviewError: async (error, reason) =>\n (await this.recoverActiveAgentAfterPreviewError(error, reason))\n ?.interface ?? null,\n });\n\n private sessionManager?: PlaygroundSessionManager;\n private sessionSetupState: 'required' | 'ready' | 'blocked' = 'ready';\n private sessionSetupBlockingReason?: string;\n\n // Track current running task\n private currentTaskId: string | null = null;\n\n // Flag to pause MJPEG polling during agent recreation or task execution\n private _agentReady = true;\n\n // Flag to track if AI config has changed and agent needs recreation\n private _configDirty = false;\n private _lastAiConfigSignature: string | null = null;\n private _baseRuntimeState?: PlaygroundRuntimeState;\n private _basePreparedMetadata?: Record<string, unknown>;\n private _baseExecutionHooks?: PlaygroundExecutionHooks;\n private _baseSidecars?: PlaygroundSidecar[];\n private _activeConnection: PlaygroundActiveConnection = {\n session: null,\n agent: null,\n agentFactory: null,\n runtime: undefined,\n executionHooks: undefined,\n sidecars: undefined,\n };\n\n private setActiveAgent(\n agent: PageAgent | null,\n options: { preserveActiveStream?: boolean } = {},\n ): void {\n this._activeConnection.agent = agent;\n // The MJPEG hub keys its producer by `activeInterface`. A bare\n // recreateAgent swaps to a new agent instance — even when the\n // underlying device/page is identical — so without a reset the next\n // /mjpeg request finds a stale producer keyed to the previous\n // interface object. `reset()` tears down the producer so the next\n // request rebuilds one. The cancel path opts out: it preserves the\n // browser page across recreates and we want the existing CDP\n // screencast subscribers to keep receiving frames without a\n // disconnect.\n if (!options.preserveActiveStream) {\n this._mjpegHandler.reset();\n }\n }\n\n constructor(\n agent?: PageAgent | (() => PageAgent) | (() => Promise<PageAgent>),\n staticPath = STATIC_PATH,\n id?: string, // Optional override ID\n ) {\n this._app = express();\n this.tmpDir = getTmpDir()!;\n this.staticPath = staticPath;\n this.taskExecutionDumps = {}; // Initialize as empty object\n // Use provided ID, or generate random UUID for each startup\n this.id = id || uuid();\n\n // Support both instance and factory function modes\n if (typeof agent === 'function') {\n this._activeConnection.agentFactory = agent;\n } else {\n this.setActiveAgent(agent || null);\n }\n }\n\n get agent(): PageAgent | null {\n return this._activeConnection.agent;\n }\n\n private assertNoActiveSessionForBaseStateUpdate(methodName: string): void {\n if (this._activeConnection.session) {\n throw new Error(\n `${methodName} cannot update prepared state while a session is active`,\n );\n }\n }\n\n private buildBaseRuntimeState(): PlaygroundRuntimeState | undefined {\n if (!this._baseRuntimeState) {\n return undefined;\n }\n\n return {\n ...this._baseRuntimeState,\n metadata: this.buildSessionMetadata(),\n };\n }\n\n private resetConnectionToBaseState(): void {\n this._activeConnection = {\n session: null,\n agent: this._activeConnection.agent,\n agentFactory: this._activeConnection.agentFactory,\n runtime: this.buildBaseRuntimeState(),\n executionHooks: this._baseExecutionHooks,\n sidecars: this._baseSidecars,\n };\n }\n\n private syncRuntimeState(): void {\n this._baseRuntimeState = {\n ...(this._baseRuntimeState || {}),\n metadata: this.buildSessionMetadata(),\n };\n\n if (this._activeConnection.session) {\n this._activeConnection = {\n ...this._activeConnection,\n runtime: this._activeConnection.runtime\n ? {\n ...this._activeConnection.runtime,\n metadata: this.buildSessionMetadata(),\n }\n : this.buildBaseRuntimeState(),\n };\n return;\n }\n\n this.resetConnectionToBaseState();\n }\n\n private restoreBaseSessionState(): void {\n this.taskExecutionDumps = {};\n this.currentTaskId = null;\n this.sessionSetupState =\n this.sessionSetupState === 'blocked' ? 'blocked' : 'required';\n this._activeConnection = {\n session: null,\n agent: null,\n agentFactory: null,\n runtime: this.buildBaseRuntimeState(),\n executionHooks: this._baseExecutionHooks,\n sidecars: this._baseSidecars,\n };\n this._mjpegHandler.reset();\n this.syncRuntimeState();\n }\n\n setPreparedPlatform(\n prepared: Pick<\n PreparedPlaygroundPlatform,\n | 'platformId'\n | 'title'\n | 'description'\n | 'preview'\n | 'metadata'\n | 'sessionManager'\n | 'executionHooks'\n | 'sidecars'\n >,\n ): void {\n // Allow overriding the initial session created by agentFactory in launch()\n if (this._activeConnection.session && this._activeConnection.agentFactory) {\n this._activeConnection.session = null;\n }\n this.assertNoActiveSessionForBaseStateUpdate('setPreparedPlatform');\n this.sessionManager = prepared.sessionManager;\n this._basePreparedMetadata = prepared.metadata\n ? { ...prepared.metadata }\n : undefined;\n this._baseRuntimeState = {\n platformId: prepared.platformId,\n title: prepared.title,\n description: prepared.description,\n preview: prepared.preview,\n metadata: this.buildSessionMetadata(),\n };\n this._baseExecutionHooks = prepared.executionHooks;\n this._baseSidecars = prepared.sidecars;\n this.resetConnectionToBaseState();\n\n if (\n this.sessionManager &&\n !this._activeConnection.agent &&\n !this._activeConnection.session\n ) {\n this.sessionSetupState =\n this._basePreparedMetadata?.setupState === 'blocked'\n ? 'blocked'\n : 'required';\n this.sessionSetupBlockingReason =\n typeof this._basePreparedMetadata?.setupBlockingReason === 'string'\n ? this._basePreparedMetadata.setupBlockingReason\n : undefined;\n }\n }\n\n setPreviewDescriptor(preview?: PlaygroundPreviewDescriptor): void {\n this.assertNoActiveSessionForBaseStateUpdate('setPreviewDescriptor');\n this._baseRuntimeState = {\n ...(this._baseRuntimeState || {}),\n preview,\n };\n this.resetConnectionToBaseState();\n }\n\n setRuntimeMetadata(metadata?: Record<string, unknown>): void {\n this.assertNoActiveSessionForBaseStateUpdate('setRuntimeMetadata');\n this._basePreparedMetadata = metadata ? { ...metadata } : undefined;\n this.syncRuntimeState();\n }\n\n getRuntimeInfo(): PlaygroundRuntimeInfo {\n return buildRuntimeInfo({\n platformId: this._activeConnection.runtime?.platformId,\n title: this._activeConnection.runtime?.title,\n platformDescription: this._activeConnection.runtime?.description,\n interfaceType:\n this._activeConnection.agent?.interface?.interfaceType || 'Unknown',\n interfaceDescription:\n this._activeConnection.agent?.interface?.describe?.() || undefined,\n preview: this._activeConnection.runtime?.preview,\n metadata: this.buildSessionMetadata(),\n supportsScreenshot:\n typeof this._activeConnection.agent?.interface?.screenshotBase64 ===\n 'function',\n mjpegStreamUrl: this._activeConnection.agent?.interface?.mjpegStreamUrl,\n scrcpyPort: this.scrcpyPort,\n });\n }\n\n /**\n * Treat a session as connected when either:\n * - we have a live agent, OR\n * - we are mid-recreate (`_agentReady === false`).\n *\n * `recreateAgent` (e.g. via /cancel) nulls `_activeConnection.agent`\n * before the factory swaps in a fresh one. Without this guard the UI\n * sees a brief `connected: false` window and flashes the\n * SessionSetupPanel (\"create agent\" form) for ~1–2 seconds.\n */\n private isEffectivelyConnected(): boolean {\n const rawConnected = this.sessionManager\n ? Boolean(\n this._activeConnection.session?.connected &&\n this._activeConnection.agent,\n )\n : Boolean(this._activeConnection.agent);\n return rawConnected || !this._agentReady;\n }\n\n getSessionInfo(): PlaygroundSessionState & {\n setupState: 'required' | 'ready' | 'blocked';\n setupBlockingReason?: string;\n } {\n return {\n connected: this.isEffectivelyConnected(),\n displayName: this._activeConnection.session?.displayName,\n metadata: {\n ...(this._activeConnection.session?.metadata || {}),\n },\n setupState: this.sessionSetupState,\n setupBlockingReason: this.sessionSetupBlockingReason,\n };\n }\n\n private buildSessionMetadata(): Record<string, unknown> {\n return {\n ...(this._basePreparedMetadata || {}),\n ...(this._activeConnection.session?.metadata || {}),\n sessionConnected: this.isEffectivelyConnected(),\n sessionDisplayName: this._activeConnection.session?.displayName,\n setupState: this.sessionSetupState,\n ...(this.sessionSetupBlockingReason\n ? { setupBlockingReason: this.sessionSetupBlockingReason }\n : {}),\n };\n }\n\n private async startSidecars(sidecars?: PlaygroundSidecar[]): Promise<void> {\n for (const sidecar of sidecars || []) {\n await sidecar.start();\n }\n }\n\n private async stopSidecars(sidecars?: PlaygroundSidecar[]): Promise<void> {\n for (const sidecar of sidecars || []) {\n await sidecar.stop?.();\n }\n }\n\n private getActiveAgentOrThrow(): PageAgent {\n if (!this._activeConnection.agent) {\n throw new Error('No active session');\n }\n\n return this._activeConnection.agent;\n }\n\n private async destroyCurrentAgent({\n preserveActiveStream = false,\n }: { preserveActiveStream?: boolean } = {}): Promise<void> {\n if (!this._activeConnection.agent) {\n return;\n }\n\n try {\n if (typeof this._activeConnection.agent.destroy === 'function') {\n await this._activeConnection.agent.destroy();\n }\n } catch (error) {\n console.warn('Failed to destroy old agent:', error);\n } finally {\n // Forward `preserveActiveStream` so the cancel path doesn't blow\n // away the MJPEG hub on the implicit `setActiveAgent(null)` that\n // happens before `recreateAgent` plugs in the replacement agent.\n this.setActiveAgent(null, { preserveActiveStream });\n // Once the stale agent is gone there is nothing left to recreate.\n this._configDirty = false;\n }\n }\n\n private async destroyCurrentSession(): Promise<void> {\n const previousSession = this._activeConnection.session;\n const previousSidecars = this._activeConnection.sidecars;\n await this.destroyCurrentAgent();\n await this.stopSidecars(previousSidecars);\n\n if (this.sessionManager?.destroySession) {\n await this.sessionManager.destroySession(previousSession || undefined);\n }\n\n this.restoreBaseSessionState();\n }\n\n private async applyCreatedSession(\n session: PlaygroundCreatedSession,\n ): Promise<void> {\n if (!session.agent && !session.agentFactory) {\n throw new Error(\n 'Session creation must provide either an agent or agentFactory',\n );\n }\n\n const sessionSidecars = session.sidecars || this._baseSidecars;\n await this.startSidecars(sessionSidecars);\n\n try {\n this._activeConnection = {\n session: {\n connected: true,\n displayName: session.displayName,\n metadata: session.metadata ? { ...session.metadata } : {},\n },\n agent: session.agent || null,\n agentFactory: session.agentFactory || null,\n runtime: {\n platformId: session.platformId ?? this._baseRuntimeState?.platformId,\n title: session.title ?? this._baseRuntimeState?.title,\n description:\n session.platformDescription ?? this._baseRuntimeState?.description,\n preview: session.preview ?? this._baseRuntimeState?.preview,\n metadata: session.metadata ? { ...session.metadata } : {},\n },\n executionHooks: session.executionHooks || this._baseExecutionHooks,\n sidecars: sessionSidecars,\n };\n this._mjpegHandler.reset();\n this.sessionSetupState = 'ready';\n this.sessionSetupBlockingReason = undefined;\n this.syncRuntimeState();\n } catch (error) {\n await this.stopSidecars(sessionSidecars).catch(() => {});\n this.restoreBaseSessionState();\n throw error;\n }\n }\n\n private async getSessionSetupSchema(\n input?: Record<string, unknown>,\n ): Promise<PlaygroundSessionSetup | null> {\n if (!this.sessionManager) {\n return null;\n }\n\n return this.sessionManager.getSetupSchema\n ? this.sessionManager.getSetupSchema(input)\n : null;\n }\n\n private async getSessionTargets(): Promise<PlaygroundSessionTarget[]> {\n if (!this.sessionManager?.listTargets) {\n return [];\n }\n\n return this.sessionManager.listTargets();\n }\n\n /**\n * Get the Express app instance for custom configuration\n *\n * IMPORTANT: Add middleware (like CORS) BEFORE calling launch()\n * The routes are initialized when launch() is called, so middleware\n * added after launch() will not affect the API routes.\n *\n * @example\n * ```typescript\n * import cors from 'cors';\n *\n * const server = new PlaygroundServer(agent);\n *\n * // Add CORS middleware before launch\n * server.app.use(cors({\n * origin: true,\n * credentials: true,\n * methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']\n * }));\n *\n * await server.launch();\n * ```\n */\n get app(): express.Application {\n return this._app;\n }\n\n /**\n * Initialize Express app with all routes and middleware\n * Called automatically by launch() if not already initialized\n */\n private initializeApp(): void {\n if (this._initialized) return;\n\n // Built-in middleware to parse JSON bodies\n this._app.use(express.json({ limit: '50mb' }));\n\n // Context update middleware (after JSON parsing)\n this._app.use(\n (req: Request, _res: Response, next: express.NextFunction) => {\n const { context } = req.body || {};\n if (\n this._activeConnection.agent &&\n context &&\n 'updateContext' in this._activeConnection.agent.interface &&\n typeof this._activeConnection.agent.interface.updateContext ===\n 'function'\n ) {\n this._activeConnection.agent.interface.updateContext(context);\n console.log('Context updated by PlaygroundServer middleware');\n }\n next();\n },\n );\n\n // NOTE: CORS middleware should be added externally via server.app.use()\n // before calling server.launch() if needed\n\n // API routes\n this.setupRoutes();\n\n // Static file serving (if staticPath is provided)\n this.setupStaticRoutes();\n\n // Error handler middleware (must be last)\n this._app.use(errorHandler);\n\n this._initialized = true;\n }\n\n filePathForUuid(uuid: string) {\n // Validate uuid to prevent path traversal attacks\n // Only allow alphanumeric characters and hyphens\n if (!/^[a-zA-Z0-9-]+$/.test(uuid)) {\n throw new Error('Invalid uuid format');\n }\n const filePath = join(this.tmpDir, `${uuid}.json`);\n // Double-check that resolved path is within tmpDir\n const resolvedPath = resolve(filePath);\n const resolvedTmpDir = resolve(this.tmpDir);\n if (!resolvedPath.startsWith(resolvedTmpDir)) {\n throw new Error('Invalid path');\n }\n return filePath;\n }\n\n saveContextFile(uuid: string, context: string) {\n const tmpFile = this.filePathForUuid(uuid);\n console.log(`save context file: ${tmpFile}`);\n writeFileSync(tmpFile, context);\n return tmpFile;\n }\n\n /**\n * Recreate agent instance (for cancellation).\n *\n * `preserveActiveStream`: skip the MJPEG hub reset so the existing\n * preview stream stays connected across the swap. Safe when the\n * agent factory reuses the same underlying page/browser (Studio Web\n * does this on cancel) — otherwise the producer would point at a\n * dead source.\n */\n private async recreateAgent({\n preserveActiveStream = false,\n }: { preserveActiveStream?: boolean } = {}): Promise<void> {\n this._agentReady = false;\n console.log('Recreating agent to cancel current task...');\n\n await this.destroyCurrentAgent({ preserveActiveStream });\n\n // Create new agent instance if factory is available\n if (this._activeConnection.agentFactory) {\n try {\n this.setActiveAgent(await this._activeConnection.agentFactory(), {\n preserveActiveStream,\n });\n this._agentReady = true;\n console.log('Agent recreated successfully');\n } catch (error) {\n this._agentReady = true;\n console.error('Failed to recreate agent:', error);\n throw error;\n }\n } else {\n this._agentReady = true;\n console.warn(\n 'Agent destroyed but cannot recreate: no factory function provided. Next /execute call will fail.',\n );\n }\n }\n\n private async recoverActiveAgentAfterPreviewError(\n error: unknown,\n reason: string,\n ): Promise<PageAgent | null> {\n if (\n !this._activeConnection.agentFactory ||\n !isRecoverablePageSessionError(error)\n ) {\n return null;\n }\n\n debugMjpeg(`Recovering active agent after ${reason}:`, error);\n try {\n this._mjpegHandler.reset();\n await this.recreateAgent();\n return this._activeConnection.agent;\n } catch (recreateError) {\n debugMjpeg(\n `Failed to recover active agent after ${reason}:`,\n recreateError,\n );\n return null;\n }\n }\n\n private findInteractAction(\n agent: PageAgent,\n actionType: string,\n ): DeviceAction<unknown> | undefined {\n return (agent.interface.actionSpace() as DeviceAction<unknown>[]).find(\n (entry) => entry.name === actionType,\n );\n }\n\n private canRunBrowserChromeInteractAction(\n agent: PageAgent,\n actionType: string,\n ): actionType is BrowserChromeInteractAction {\n return (\n actionType === 'Stop' &&\n typeof (agent.interface as BrowserChromeInterface).stopLoading ===\n 'function'\n );\n }\n\n private async runBrowserChromeInteractAction(\n agent: PageAgent,\n actionType: BrowserChromeInteractAction,\n ): Promise<void> {\n switch (actionType) {\n case 'Stop':\n await (agent.interface as BrowserChromeInterface).stopLoading?.();\n return;\n }\n }\n\n private async runInteractAction(\n agent: PageAgent,\n actionType: string,\n params: Record<string, unknown>,\n ): Promise<void> {\n if (this.canRunBrowserChromeInteractAction(agent, actionType)) {\n await this.runBrowserChromeInteractAction(agent, actionType);\n return;\n }\n\n const action = this.findInteractAction(agent, actionType);\n if (!action || typeof action.call !== 'function') {\n throw new Error(\n `Action \"${actionType}\" is not available on the current device`,\n );\n }\n\n await action.call(params, createManualExecutorContext(actionType, params));\n }\n\n /**\n * Setup all API routes\n */\n private setupRoutes(): void {\n this._app.get('/status', async (req: Request, res: Response) => {\n res.send({\n status: 'ok',\n id: this.id,\n });\n });\n\n this._app.get('/session', async (_req: Request, res: Response) => {\n res.json(this.getSessionInfo());\n });\n\n this._app.get('/session/setup', async (req: Request, res: Response) => {\n try {\n const setup = await this.getSessionSetupSchema(\n Object.fromEntries(\n Object.entries(req.query).filter(\n ([, value]) => typeof value === 'string',\n ),\n ),\n );\n if (!setup) {\n return res.status(404).json({\n error: 'Session setup is not available for this playground',\n });\n }\n\n const targets = await this.getSessionTargets();\n res.json({\n ...setup,\n targets: targets.length > 0 ? targets : setup.targets,\n });\n } catch (error) {\n res.status(500).json({\n error:\n error instanceof Error\n ? error.message\n : 'Failed to load session setup',\n });\n }\n });\n\n this._app.get('/session/targets', async (_req: Request, res: Response) => {\n try {\n res.json(await this.getSessionTargets());\n } catch (error) {\n res.status(500).json({\n error:\n error instanceof Error\n ? error.message\n : 'Failed to load session targets',\n });\n }\n });\n\n this._app.post('/session', async (req: Request, res: Response) => {\n if (!this.sessionManager) {\n return res.status(404).json({\n error: 'Session creation is not available for this playground',\n });\n }\n\n if (this.currentTaskId) {\n return res.status(409).json({\n error: 'Cannot replace session while a task is running',\n });\n }\n\n try {\n await this.destroyCurrentSession();\n const created = await this.sessionManager.createSession(req.body || {});\n await this.applyCreatedSession(created);\n\n if (\n !this._activeConnection.agent &&\n this._activeConnection.agentFactory\n ) {\n this.setActiveAgent(await this._activeConnection.agentFactory());\n }\n\n if (this._configDirty && this._activeConnection.agentFactory) {\n this._configDirty = false;\n await this.recreateAgent();\n }\n\n res.json({\n session: this.getSessionInfo(),\n runtimeInfo: this.getRuntimeInfo(),\n });\n } catch (error) {\n const failedSessionSidecars = this._activeConnection.session\n ? this._activeConnection.sidecars\n : undefined;\n await this.destroyCurrentAgent();\n await this.stopSidecars(failedSessionSidecars).catch(() => {});\n this.restoreBaseSessionState();\n res.status(400).json({\n error:\n error instanceof Error ? error.message : 'Failed to create session',\n });\n }\n });\n\n this._app.delete('/session', async (_req: Request, res: Response) => {\n if (this.currentTaskId) {\n return res.status(409).json({\n error: 'Cannot destroy session while a task is running',\n });\n }\n\n try {\n await this.destroyCurrentSession();\n res.json({\n session: this.getSessionInfo(),\n runtimeInfo: this.getRuntimeInfo(),\n });\n } catch (error) {\n res.status(500).json({\n error:\n error instanceof Error\n ? error.message\n : 'Failed to destroy session',\n });\n }\n });\n\n this._app.get('/context/:uuid', async (req: Request, res: Response) => {\n const { uuid } = req.params;\n let contextFile: string;\n try {\n contextFile = this.filePathForUuid(uuid);\n } catch {\n return res.status(400).json({\n error: 'Invalid uuid format',\n });\n }\n\n if (!existsSync(contextFile)) {\n return res.status(404).json({\n error: 'Context not found',\n });\n }\n\n const context = readFileSync(contextFile, 'utf8');\n res.json({\n context,\n });\n });\n\n this._app.get(\n '/task-progress/:requestId',\n async (req: Request, res: Response) => {\n const { requestId } = req.params;\n const executionDump = this.taskExecutionDumps[requestId] || null;\n\n res.json({\n executionDump,\n });\n },\n );\n\n this._app.post('/action-space', async (req: Request, res: Response) => {\n try {\n const agent = this.getActiveAgentOrThrow();\n let actionSpace = [];\n\n actionSpace = agent.interface.actionSpace();\n\n // Process actionSpace to make paramSchema serializable with shape info\n const processedActionSpace = actionSpace.map((action: unknown) => {\n if (action && typeof action === 'object' && 'paramSchema' in action) {\n const typedAction = action as {\n paramSchema?: { shape?: object; [key: string]: unknown };\n [key: string]: unknown;\n };\n if (\n typedAction.paramSchema &&\n typeof typedAction.paramSchema === 'object'\n ) {\n // Extract shape information from Zod schema\n let processedSchema = null;\n\n try {\n // Extract shape from runtime Zod object\n if (\n typedAction.paramSchema.shape &&\n typeof typedAction.paramSchema.shape === 'object'\n ) {\n const rawShape = typedAction.paramSchema.shape as Record<\n string,\n any\n >;\n const serializedShape: Record<string, any> = {};\n for (const [key, field] of Object.entries(rawShape)) {\n serializedShape[key] = serializeZodField(field);\n }\n processedSchema = {\n type: 'ZodObject',\n shape: serializedShape,\n };\n }\n } catch (e) {\n const actionName =\n 'name' in typedAction && typeof typedAction.name === 'string'\n ? typedAction.name\n : 'unknown';\n console.warn(\n 'Failed to process paramSchema for action:',\n actionName,\n e,\n );\n }\n\n return {\n ...typedAction,\n paramSchema: processedSchema,\n };\n }\n }\n return action;\n });\n\n res.json(processedActionSpace);\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error('Failed to get action space:', error);\n res.status(errorMessage === 'No active session' ? 409 : 500).json({\n error: errorMessage,\n });\n }\n });\n\n // -------------------------\n // actions from report file\n this._app.post(\n '/playground-with-context',\n async (req: Request, res: Response) => {\n const context = req.body.context;\n\n if (!context) {\n return res.status(400).json({\n error: 'context is required',\n });\n }\n\n const requestId = uuid();\n this.saveContextFile(requestId, context);\n return res.json({\n location: `/playground/${requestId}`,\n uuid: requestId,\n });\n },\n );\n\n this._app.post('/execute', async (req: Request, res: Response) => {\n let agent: PageAgent;\n try {\n agent = this.getActiveAgentOrThrow();\n } catch (error) {\n return res.status(409).json({\n error: error instanceof Error ? error.message : 'No active session',\n });\n }\n\n const {\n type,\n prompt,\n params,\n requestId,\n deepLocate,\n deepThink,\n screenshotIncluded,\n domIncluded,\n deviceOptions,\n } = req.body;\n\n if (!type) {\n return res.status(400).json({\n error: 'type is required',\n });\n }\n\n // Recreate agent only when AI config has changed (via /config API)\n if (this._activeConnection.agentFactory && this._configDirty) {\n this._configDirty = false;\n this._agentReady = false;\n console.log('AI config changed, recreating agent...');\n try {\n await this.destroyCurrentAgent();\n this.setActiveAgent(await this._activeConnection.agentFactory());\n agent = this.getActiveAgentOrThrow();\n this._agentReady = true;\n console.log('Agent recreated with new config');\n } catch (error) {\n this._agentReady = true;\n console.error('Failed to recreate agent:', error);\n return res.status(500).json({\n error: `Failed to create agent: ${error instanceof Error ? error.message : 'Unknown error'}`,\n });\n }\n }\n\n // Update device options if provided\n if (deviceOptions) {\n const iface = agent.interface as unknown as {\n options?: Record<string, unknown>;\n };\n iface.options = {\n ...(iface.options || {}),\n ...deviceOptions,\n };\n }\n\n // Check if another task is running\n if (this.currentTaskId) {\n return res.status(409).json({\n error: 'Another task is already running',\n currentTaskId: this.currentTaskId,\n });\n }\n\n // Lock this task\n if (requestId) {\n this.currentTaskId = requestId;\n this.taskExecutionDumps[requestId] = null;\n\n // Use onDumpUpdate to receive and store executionDump directly\n agent.onDumpUpdate = (_dump: string, executionDump?: ExecutionDump) => {\n if (executionDump) {\n // Store the execution dump directly without transformation\n this.taskExecutionDumps[requestId] = executionDump;\n }\n };\n }\n\n const response: {\n result: unknown;\n dump: ExecutionDump | null;\n error: string | null;\n reportHTML: string | null;\n requestId?: string;\n } = {\n result: null,\n dump: null,\n error: null,\n reportHTML: null,\n requestId,\n };\n\n const startTime = Date.now();\n try {\n await this._activeConnection.executionHooks?.beforeExecute?.();\n\n // Get action space to check for dynamic actions\n const actionSpace = agent.interface.actionSpace();\n\n // Prepare value object for executeAction\n const value = {\n type,\n prompt,\n params,\n };\n\n response.result = await executeAction(agent, type, actionSpace, value, {\n deepLocate,\n deepThink,\n screenshotIncluded,\n domIncluded,\n deviceOptions,\n });\n } catch (error: unknown) {\n response.error = formatErrorMessage(error);\n } finally {\n try {\n await this._activeConnection.executionHooks?.afterExecute?.();\n } catch (hookError) {\n console.error('Failed to run execution after hook:', hookError);\n }\n }\n\n try {\n const dumpString = agent.dumpDataString({\n inlineScreenshots: true,\n });\n if (dumpString) {\n const groupedDump = ReportActionDump.fromSerializedString(dumpString);\n // Extract first execution from grouped dump, matching local execution adapter behavior\n response.dump = groupedDump.executions?.[0] || null;\n } else {\n response.dump = null;\n }\n response.reportHTML =\n agent.reportHTMLString({ inlineScreenshots: true }) || null;\n\n agent.writeOutActionDumps();\n agent.resetDump();\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(\n `write out dump failed: requestId: ${requestId}, ${errorMessage}`,\n );\n } finally {\n }\n\n res.send(response);\n const timeCost = Date.now() - startTime;\n\n if (response.error) {\n console.error(\n `handle request failed after ${timeCost}ms: requestId: ${requestId}, ${response.error}`,\n );\n } else {\n console.log(\n `handle request done after ${timeCost}ms: requestId: ${requestId}`,\n );\n }\n\n // Clean up task execution dumps and unlock after execution completes\n if (requestId) {\n delete this.taskExecutionDumps[requestId];\n // Release the lock\n if (this.currentTaskId === requestId) {\n this.currentTaskId = null;\n }\n }\n });\n\n this._app.post(\n '/cancel/:requestId',\n async (req: Request, res: Response) => {\n const { requestId } = req.params;\n\n if (!requestId) {\n return res.status(400).json({\n error: 'requestId is required',\n });\n }\n\n try {\n const agent = this.getActiveAgentOrThrow();\n // Check if this is the current running task\n if (this.currentTaskId !== requestId) {\n return res.json({\n status: 'not_found',\n message: 'Task not found or already completed',\n });\n }\n\n console.log(`Cancelling task: ${requestId}`);\n\n // Get current execution data before cancelling (dump and reportHTML)\n let dump: any = null;\n let reportHTML: string | null = null;\n\n try {\n const dumpString = agent.dumpDataString?.({\n inlineScreenshots: true,\n });\n if (dumpString) {\n const groupedDump =\n ReportActionDump.fromSerializedString(dumpString);\n // Extract first execution from grouped dump\n dump = groupedDump.executions?.[0] || null;\n }\n\n reportHTML =\n agent.reportHTMLString?.({\n inlineScreenshots: true,\n }) || null;\n } catch (error: unknown) {\n console.warn('Failed to get execution data before cancel:', error);\n }\n\n // Destroy and recreate agent to cancel the current task,\n // while keeping the live preview stream alive so the user\n // doesn't see a 3–5s blackout / page reload when they hit\n // Stop. Platform factories that reuse the same device or\n // page across recreates (e.g. Studio Web) honor this hint.\n try {\n await this.recreateAgent({ preserveActiveStream: true });\n } catch (error) {\n console.warn('Failed to recreate agent during cancel:', error);\n }\n\n // Clean up\n delete this.taskExecutionDumps[requestId];\n this.currentTaskId = null;\n\n res.json({\n status: 'cancelled',\n message: 'Task cancelled successfully',\n dump,\n reportHTML,\n });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to cancel: ${errorMessage}`);\n res.status(errorMessage === 'No active session' ? 409 : 500).json({\n error: `Failed to cancel: ${errorMessage}`,\n });\n }\n },\n );\n\n // Screenshot API for real-time screenshot polling\n this._app.get('/screenshot', async (_req: Request, res: Response) => {\n try {\n let agent = this.getActiveAgentOrThrow();\n // Check if page has screenshotBase64 method\n if (typeof agent.interface.screenshotBase64 !== 'function') {\n return res.status(500).json({\n error: 'Screenshot method not available on current interface',\n });\n }\n\n let screenshot: string;\n try {\n screenshot = await agent.interface.screenshotBase64();\n } catch (error) {\n const recoveredAgent = await this.recoverActiveAgentAfterPreviewError(\n error,\n 'screenshot capture',\n );\n if (\n !recoveredAgent ||\n typeof recoveredAgent.interface.screenshotBase64 !== 'function'\n ) {\n throw error;\n }\n agent = recoveredAgent;\n screenshot = await agent.interface.screenshotBase64();\n }\n\n res.json({\n screenshot,\n timestamp: Date.now(),\n });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n const statusCode = errorMessage === 'No active session' ? 409 : 500;\n if (statusCode !== 409) {\n console.error(`Failed to take screenshot: ${errorMessage}`);\n }\n res.status(statusCode).json({\n error: `Failed to take screenshot: ${errorMessage}`,\n });\n }\n });\n\n // MJPEG streaming endpoint for real-time screen preview. The actual\n // probe / proxy / in-process producer / polling logic lives in\n // MjpegStreamHandler so this route is just HTTP plumbing.\n this._app.get('/mjpeg', async (req: Request, res: Response) => {\n const agent = this._activeConnection.agent;\n if (!agent) {\n return res.status(409).json({ error: 'No active session' });\n }\n await this._mjpegHandler.serve(req, res);\n });\n\n // Interface info API for getting interface type and description\n this._app.get('/interface-info', async (_req: Request, res: Response) => {\n try {\n const runtimeInfo = this.getRuntimeInfo();\n const agent = this._activeConnection.agent;\n let size: { width: number; height: number } | undefined;\n let navigationState: { isLoading: boolean } | undefined;\n let actionTypes: string[] | undefined;\n if (typeof agent?.interface?.size === 'function') {\n try {\n size = await agent.interface.size();\n } catch (error) {\n debugScreenshot('interface size() failed:', error);\n }\n }\n if (typeof agent?.interface?.navigationState === 'function') {\n try {\n navigationState = await agent.interface.navigationState();\n } catch (error) {\n debugScreenshot('interface navigationState() failed:', error);\n }\n }\n if (typeof agent?.interface?.actionSpace === 'function') {\n try {\n const actions = agent.interface.actionSpace();\n actionTypes = Array.isArray(actions)\n ? actions\n .map((action) => action?.name)\n .filter((name): name is string => typeof name === 'string')\n : undefined;\n } catch (error) {\n debugScreenshot('interface actionSpace() failed:', error);\n }\n }\n\n res.json({\n type: runtimeInfo.interface.type,\n description: runtimeInfo.interface.description,\n ...(size ? { size } : {}),\n ...(navigationState ? { navigationState } : {}),\n ...(actionTypes ? { actionTypes } : {}),\n });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to get interface info: ${errorMessage}`);\n res.status(500).json({\n error: `Failed to get interface info: ${errorMessage}`,\n });\n }\n });\n\n // Direct manipulation API – invokes a named action immediately, bypassing\n // AI planning, the task lock, and dump bookkeeping. Primitive-capable\n // device previews use the typed input surface; browser navigation falls\n // back to explicit actionSpace/browser-chrome actions.\n this._app.post('/interact', async (req: Request, res: Response) => {\n let agent: PageAgent;\n try {\n agent = this.getActiveAgentOrThrow();\n } catch (error) {\n return res.status(409).json({\n error: error instanceof Error ? error.message : 'No active session',\n });\n }\n\n const { actionType } = req.body ?? {};\n if (typeof actionType !== 'string' || !actionType) {\n return res.status(400).json({\n error: 'actionType is required',\n });\n }\n\n try {\n const inputPrimitives = agent.interface.inputPrimitives;\n if (inputPrimitives) {\n await dispatchPointer(inputPrimitives, req.body ?? {}, () =>\n agent.interface.size(),\n );\n res.json({});\n return;\n }\n\n if (\n !this.findInteractAction(agent, actionType) &&\n !this.canRunBrowserChromeInteractAction(agent, actionType)\n ) {\n return res.status(404).json({\n error: isPointerInteractActionType(actionType)\n ? 'Manual control is not supported on this device'\n : `Action \"${actionType}\" is not available on the current device`,\n });\n }\n\n const params = buildInteractParams(actionType, req.body ?? {});\n await this.runInteractAction(agent, actionType, params);\n res.json({});\n } catch (error: unknown) {\n if (error instanceof PointerInputError) {\n return res.status(error.statusCode).json({ error: error.message });\n }\n if (error instanceof InteractParamsValidationError) {\n return res.status(400).json({ error: error.message });\n }\n\n const recoveredAgent = await this.recoverActiveAgentAfterPreviewError(\n error,\n `manual interact action \"${actionType}\"`,\n );\n if (recoveredAgent) {\n return res.status(409).json({\n error:\n 'The page session was closed and has been recreated. Please retry the action.',\n });\n }\n\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(\n `Failed to run interact action \"${actionType}\": ${errorMessage}`,\n );\n res.status(500).json({ error: errorMessage });\n }\n });\n\n this._app.get('/runtime-info', async (_req: Request, res: Response) => {\n try {\n res.json(this.getRuntimeInfo());\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to get runtime info: ${errorMessage}`);\n res.status(500).json({\n error: `Failed to get runtime info: ${errorMessage}`,\n });\n }\n });\n\n this.app.post('/config', async (req: Request, res: Response) => {\n const { aiConfig } = req.body;\n\n if (!aiConfig || typeof aiConfig !== 'object') {\n return res.status(400).json({\n error: 'aiConfig is required and must be an object',\n });\n }\n\n if (Object.keys(aiConfig).length === 0) {\n return res.json({\n status: 'ok',\n message: 'AI config not changed due to empty object',\n });\n }\n\n const nextConfigSignature = serializeAiConfigSignature(aiConfig);\n const configChanged = nextConfigSignature !== this._lastAiConfigSignature;\n\n try {\n if (configChanged) {\n overrideAIConfig(aiConfig);\n this._lastAiConfigSignature = nextConfigSignature;\n this._configDirty = Boolean(this._activeConnection.agent);\n }\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to update AI config: ${errorMessage}`);\n return res.status(500).json({\n error: `Failed to update AI config: ${errorMessage}`,\n });\n }\n\n if (!configChanged) {\n return res.json({\n status: 'ok',\n message: 'AI config not changed because it is identical to current',\n });\n }\n\n // Validate the config immediately so the frontend gets early feedback\n try {\n globalModelConfigManager.getModelConfig('default');\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`AI config validation failed: ${errorMessage}`);\n return res.status(400).json({\n error: errorMessage,\n });\n }\n\n return res.json({\n status: 'ok',\n message: this._configDirty\n ? 'AI config updated. Agent will be recreated on next execution.'\n : 'AI config updated. New sessions will use it immediately.',\n });\n });\n\n this.app.post(\n '/connectivity-test',\n async (_req: Request, res: Response) => {\n try {\n const result = await runConnectivityTest({\n defaultModelConfig:\n globalModelConfigManager.getModelConfig('default'),\n planningModelConfig:\n globalModelConfigManager.getModelConfig('planning'),\n insightModelConfig:\n globalModelConfigManager.getModelConfig('insight'),\n });\n return res.json(result);\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Connectivity test failed: ${errorMessage}`);\n return res.status(500).json({\n error: errorMessage,\n });\n }\n },\n );\n }\n\n /**\n * Setup static file serving routes\n */\n private setupStaticRoutes(): void {\n // Handle index.html with port injection\n this._app.get('/', (_req: Request, res: Response) => {\n this.serveHtmlWithPorts(res);\n });\n\n this._app.get('/index.html', (_req: Request, res: Response) => {\n this.serveHtmlWithPorts(res);\n });\n\n // Use express.static middleware for secure static file serving\n this._app.use(express.static(this.staticPath));\n\n // Fallback to index.html for SPA routing\n this._app.get('*', (_req: Request, res: Response) => {\n this.serveHtmlWithPorts(res);\n });\n }\n\n /**\n * Serve HTML with injected port configuration\n */\n private serveHtmlWithPorts(res: Response): void {\n try {\n const htmlPath = join(this.staticPath, 'index.html');\n let html = readFileSync(htmlPath, 'utf8');\n\n const scrcpyPort = this.scrcpyPort ?? this.port! + 1;\n\n // Inject scrcpy port configuration script into HTML head\n const configScript = `\n <script>\n window.SCRCPY_PORT = ${scrcpyPort};\n </script>\n `;\n\n // Insert the script before closing </head> tag\n html = html.replace('</head>', `${configScript}</head>`);\n\n res.setHeader('Content-Type', 'text/html');\n res.send(html);\n } catch (error) {\n console.error('Error serving HTML with ports:', error);\n res.status(500).send('Internal Server Error');\n }\n }\n\n /**\n * Launch the server on specified port\n */\n async launch(port?: number): Promise<PlaygroundServer> {\n // If using factory mode, initialize agent\n if (this._activeConnection.agentFactory && !this.sessionManager) {\n console.log('Initializing agent from factory function...');\n this.setActiveAgent(await this._activeConnection.agentFactory());\n this._activeConnection.session = {\n connected: true,\n metadata: {},\n };\n this.sessionSetupState = 'ready';\n this.syncRuntimeState();\n console.log('Agent initialized successfully');\n }\n\n // Initialize routes now, after any middleware has been added\n this.initializeApp();\n\n this.port = port || defaultPort;\n\n return new Promise((resolve) => {\n const serverPort = this.port ?? defaultPort;\n this.server = this._app.listen(serverPort, '0.0.0.0', () => {\n resolve(this);\n });\n });\n }\n\n /**\n * Close the server and clean up resources\n */\n async close(): Promise<void> {\n await this.destroyCurrentSession().catch((error) => {\n console.warn('Failed to destroy current session during shutdown:', error);\n });\n this._mjpegHandler.shutdown();\n\n return new Promise((resolve, reject) => {\n if (this.server) {\n this.taskExecutionDumps = {};\n\n // Close the server\n this.server.close((error) => {\n if (error) {\n reject(error);\n } else {\n this.server = undefined;\n resolve();\n }\n });\n } else {\n resolve();\n }\n });\n }\n}\n\nexport default PlaygroundServer;\nexport { PlaygroundServer };\n"],"names":["defaultPort","PLAYGROUND_SERVER_PORT","serializeAiConfigSignature","aiConfig","JSON","Object","leftKey","rightKey","serializeZodField","field","def","typeName","result","Array","rawShape","serializedShape","k","v","__filename","fileURLToPath","__dirname","dirname","STATIC_PATH","join","debugScreenshot","getDebug","debugMjpeg","InteractParamsValidationError","Error","message","requireNumber","value","Number","locateFromPoint","x","y","fieldX","fieldY","description","generateElementByPoint","Math","POINTER_INTERACT_ACTIONS","Set","isPointerInteractActionType","actionType","buildLocateActionParams","body","params","buildSwipeParams","buildDragAndDropParams","buildKeyboardPressParams","buildInputParams","getManualInteractParamBuilder","buildInteractParams","builder","_omit","passthrough","createManualExecutorContext","param","task","undefined","uuid","errorHandler","err","req","res","next","console","errorMessage","RECOVERABLE_PAGE_SESSION_ERROR_PATTERN","isRecoverablePageSessionError","error","String","PlaygroundServer","agent","options","methodName","prepared","preview","metadata","buildRuntimeInfo","rawConnected","Boolean","sidecars","sidecar","preserveActiveStream","previousSession","previousSidecars","session","sessionSidecars","input","express","_res","context","filePath","resolvedPath","resolve","resolvedTmpDir","tmpFile","writeFileSync","reason","recreateError","entry","action","_req","setup","targets","created","failedSessionSidecars","contextFile","existsSync","readFileSync","requestId","executionDump","actionSpace","processedActionSpace","typedAction","processedSchema","key","e","actionName","type","prompt","deepLocate","deepThink","screenshotIncluded","domIncluded","deviceOptions","iface","_dump","response","startTime","Date","executeAction","formatErrorMessage","hookError","dumpString","groupedDump","ReportActionDump","timeCost","dump","reportHTML","screenshot","recoveredAgent","statusCode","runtimeInfo","size","navigationState","actionTypes","actions","name","inputPrimitives","dispatchPointer","PointerInputError","nextConfigSignature","configChanged","overrideAIConfig","globalModelConfigManager","runConnectivityTest","htmlPath","html","scrcpyPort","configScript","port","Promise","serverPort","reject","staticPath","id","MjpegStreamHandler","getTmpDir"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,MAAMA,cAAcC;AAEpB,SAASC,2BAA2BC,QAAiC;IACnE,OAAOC,KAAK,SAAS,CACnBC,OAAO,OAAO,CAACF,UAAU,IAAI,CAAC,CAAC,CAACG,QAAQ,EAAE,CAACC,SAAS,GAClDD,QAAQ,aAAa,CAACC;AAG5B;AAOO,SAASC,kBAAkBC,KAAU;IAC1C,IAAI,CAACA,SAAS,AAAiB,YAAjB,OAAOA,OAAoB,OAAOA;IAEhD,MAAMC,MAAMD,MAAM,IAAI;IACtB,IAAI,CAACC,OAAO,AAAe,YAAf,OAAOA,KAAkB,OAAOD;IAE5C,MAAME,WAA+BD,IAAI,QAAQ;IAEjD,MAAME,SAA8B;QAClC,MAAM;YACJD;QACF;IACF;IAGA,IAAID,IAAI,WAAW,EACjBE,OAAO,IAAI,CAAC,WAAW,GAAGF,IAAI,WAAW;IAI3C,IAAIA,IAAI,SAAS,EACfE,OAAO,IAAI,CAAC,SAAS,GAAGJ,kBAAkBE,IAAI,SAAS;IAIzD,IAAIC,AAAa,iBAAbA,YAA6B,AAA4B,cAA5B,OAAOD,IAAI,YAAY,EACtD,IAAI;QACFE,OAAO,IAAI,CAAC,uBAAuB,GAAGF,IAAI,YAAY;IACxD,EAAE,OAAM,CAER;IAIF,IAAIC,AAAa,cAAbA,YAA0BE,MAAM,OAAO,CAACH,IAAI,MAAM,GACpDE,OAAO,IAAI,CAAC,MAAM,GAAGF,IAAI,MAAM;IAIjC,IAAIC,AAAa,gBAAbA,UAA0B;QAC5B,MAAMG,WAAW,AAAqB,cAArB,OAAOJ,IAAI,KAAK,GAAkBA,IAAI,KAAK,KAAKA,IAAI,KAAK;QAC1E,IAAII,YAAY,AAAoB,YAApB,OAAOA,UAAuB;YAC5C,MAAMC,kBAAuC,CAAC;YAC9C,KAAK,MAAM,CAACC,GAAGC,EAAE,IAAIZ,OAAO,OAAO,CAACS,UAClCC,eAAe,CAACC,EAAE,GAAGR,kBAAkBS;YAEzCL,OAAO,IAAI,CAAC,KAAK,GAAGG;YACpBH,OAAO,KAAK,GAAGG;QACjB;IACF;IAGA,IAAIN,MAAM,WAAW,EACnBG,OAAO,WAAW,GAAGH,MAAM,WAAW;IAGxC,OAAOG;AACT;AAGA,MAAMM,kBAAaC,cAAc,YAAY,GAAG;AAChD,MAAMC,iBAAYC,QAAQH;AAC1B,MAAMI,cAAcC,KAAKH,gBAAW,MAAM,MAAM;AAEhD,MAAMI,kBAAkBC,SAAS,yBAAyB;IAAE,SAAS;AAAK;AAC1E,MAAMC,aAAaD,SAAS,oBAAoB;IAAE,SAAS;AAAK;AAOzD,MAAME,sCAAsCC;IACjD,YAAYC,OAAe,CAAE;QAC3B,KAAK,CAACA;QACN,IAAI,CAAC,IAAI,GAAG;IACd;AACF;AAEA,SAASC,cAAcC,KAAc,EAAEtB,KAAa;IAClD,IAAI,AAAiB,YAAjB,OAAOsB,SAAsBC,OAAO,KAAK,CAACD,QAC5C,MAAM,IAAIJ,8BACR,GAAGlB,MAAM,iCAAiC,CAAC;IAG/C,OAAOsB;AACT;AAEA,SAASE,gBACPC,CAAU,EACVC,CAAU,EACVC,MAAc,EACdC,MAAc,EACdC,WAAmB;IAEnB,OAAOC,uBACL;QACEC,KAAK,KAAK,CAACV,cAAcI,GAAGE;QAC5BI,KAAK,KAAK,CAACV,cAAcK,GAAGE;KAC7B,EACDC;AAEJ;AAaA,MAAMG,2BAA2B,IAAIC,IAAI;IACvC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,SAASC,4BAA4BC,UAAkB;IACrD,OAAOH,yBAAyB,GAAG,CAACG;AACtC;AAEA,MAAMC,0BAAgD,CAACC,MAAMF;IAC3D,MAAMG,SAAkC;QACtC,QAAQd,gBAAgBa,KAAK,CAAC,EAAEA,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,OAAO,EAAEF,YAAY;IAC1E;IACA,IAAI,AAAyB,YAAzB,OAAOE,KAAK,QAAQ,EACtBC,OAAO,QAAQ,GAAGD,KAAK,QAAQ;IAEjC,OAAOC;AACT;AAEA,MAAMC,mBAAyC,CAACF;IAC9C,MAAMC,SAAkC;QACtC,OAAOd,gBAAgBa,KAAK,CAAC,EAAEA,KAAK,CAAC,EAAE,KAAK,KAAK;QACjD,KAAKb,gBACHa,KAAK,IAAI,EACTA,KAAK,IAAI,EACT,QACA,QACA;IAEJ;IACA,IAAI,AAAyB,YAAzB,OAAOA,KAAK,QAAQ,EAAeC,OAAO,QAAQ,GAAGD,KAAK,QAAQ;IACtE,IAAI,AAAuB,YAAvB,OAAOA,KAAK,MAAM,EAAeC,OAAO,MAAM,GAAGD,KAAK,MAAM;IAChE,OAAOC;AACT;AAEA,MAAME,yBAA+C,CAACH,OAAU;QAC9D,MAAMb,gBAAgBa,KAAK,CAAC,EAAEA,KAAK,CAAC,EAAE,KAAK,KAAK;QAChD,IAAIb,gBAAgBa,KAAK,IAAI,EAAEA,KAAK,IAAI,EAAE,QAAQ,QAAQ;IAC5D;AAEA,MAAMI,2BAAiD,CAACJ;IACtD,IAAI,AAAwB,YAAxB,OAAOA,KAAK,OAAO,EACrB,MAAM,IAAInB,8BACR;IAGJ,MAAMoB,SAAkC;QAAE,SAASD,KAAK,OAAO;IAAC;IAChE,IAAI,AAAkB,YAAlB,OAAOA,KAAK,CAAC,IAAiB,AAAkB,YAAlB,OAAOA,KAAK,CAAC,EAC7CC,OAAO,MAAM,GAAGd,gBACda,KAAK,CAAC,EACNA,KAAK,CAAC,EACN,KACA,KACA;IAGJ,OAAOC;AACT;AAEA,MAAMI,mBAAyC,CAACL;IAC9C,IAAI,AAAsB,YAAtB,OAAOA,KAAK,KAAK,EACnB,MAAM,IAAInB,8BAA8B;IAE1C,MAAMoB,SAAkC;QAAE,OAAOD,KAAK,KAAK;IAAC;IAC5D,IAAI,AAAkB,YAAlB,OAAOA,KAAK,CAAC,IAAiB,AAAkB,YAAlB,OAAOA,KAAK,CAAC,EAC7CC,OAAO,MAAM,GAAGd,gBAAgBa,KAAK,CAAC,EAAEA,KAAK,CAAC,EAAE,KAAK,KAAK;IAE5D,IAAI,AAAqB,YAArB,OAAOA,KAAK,IAAI,EAAeC,OAAO,IAAI,GAAGD,KAAK,IAAI;IAC1D,IAAI,AAAoC,aAApC,OAAOA,KAAK,mBAAmB,EACjCC,OAAO,mBAAmB,GAAGD,KAAK,mBAAmB;IAEvD,OAAOC;AACT;AAEA,SAASK,8BACPR,UAAkB;IAElB,OAAQA;QACN,KAAK;QACL,KAAK;QACL,KAAK;QACL,KAAK;QACL,KAAK;YACH,OAAOC;QACT,KAAK;YACH,OAAOG;QACT,KAAK;YACH,OAAOC;QACT,KAAK;YACH,OAAOC;QACT,KAAK;YACH,OAAOC;QACT;YACE;IACJ;AACF;AAEO,SAASE,oBACdT,UAAkB,EAClBE,IAA6B;IAE7B,MAAMQ,UAAUF,8BAA8BR;IAC9C,IAAIU,SACF,OAAOA,QAAQR,MAAMF;IAGvB,MAAM,EAAE,YAAYW,KAAK,EAAE,GAAGC,aAAa,GAAGV;IAC9C,OAAOU;AACT;AAEO,SAASC,4BACdb,UAAkB,EAClBc,KAAc;IAEd,MAAMC,OAAsB;QAC1B,MAAM;QACN,SAASf;QACTc;QACA,UAAU,UAAYE;QACtB,QAAQ,CAAC,OAAO,EAAEC,cAAQ;QAC1B,QAAQ;IACV;IACA,OAAO;QAAEF;IAAK;AAChB;AACA,MAAMG,eAAe,CACnBC,KACAC,KACAC,KACAC;IAEAC,QAAQ,KAAK,CAACJ;IACd,MAAMK,eACJL,eAAenC,QAAQmC,IAAI,OAAO,GAAG;IACvCE,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;QACnB,OAAOG;IACT;AACF;AAmBA,MAAMC,yCACJ;AAEF,SAASC,8BAA8BC,KAAc;IACnD,MAAM1C,UAAU0C,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAGC,OAAOD;IAChE,OAAOF,uCAAuC,IAAI,CAACxC;AACrD;AAEA,MAAM4C;IAyDI,eACNC,KAAuB,EACvBC,UAA8C,CAAC,CAAC,EAC1C;QACN,IAAI,CAAC,iBAAiB,CAAC,KAAK,GAAGD;QAU/B,IAAI,CAACC,QAAQ,oBAAoB,EAC/B,IAAI,CAAC,aAAa,CAAC,KAAK;IAE5B;IAsBA,IAAI,QAA0B;QAC5B,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK;IACrC;IAEQ,wCAAwCC,UAAkB,EAAQ;QACxE,IAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAChC,MAAM,IAAIhD,MACR,GAAGgD,WAAW,uDAAuD,CAAC;IAG5E;IAEQ,wBAA4D;QAClE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EACzB;QAGF,OAAO;YACL,GAAG,IAAI,CAAC,iBAAiB;YACzB,UAAU,IAAI,CAAC,oBAAoB;QACrC;IACF;IAEQ,6BAAmC;QACzC,IAAI,CAAC,iBAAiB,GAAG;YACvB,SAAS;YACT,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK;YACnC,cAAc,IAAI,CAAC,iBAAiB,CAAC,YAAY;YACjD,SAAS,IAAI,CAAC,qBAAqB;YACnC,gBAAgB,IAAI,CAAC,mBAAmB;YACxC,UAAU,IAAI,CAAC,aAAa;QAC9B;IACF;IAEQ,mBAAyB;QAC/B,IAAI,CAAC,iBAAiB,GAAG;YACvB,GAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC;YAChC,UAAU,IAAI,CAAC,oBAAoB;QACrC;QAEA,IAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;YAClC,IAAI,CAAC,iBAAiB,GAAG;gBACvB,GAAG,IAAI,CAAC,iBAAiB;gBACzB,SAAS,IAAI,CAAC,iBAAiB,CAAC,OAAO,GACnC;oBACE,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO;oBACjC,UAAU,IAAI,CAAC,oBAAoB;gBACrC,IACA,IAAI,CAAC,qBAAqB;YAChC;YACA;QACF;QAEA,IAAI,CAAC,0BAA0B;IACjC;IAEQ,0BAAgC;QACtC,IAAI,CAAC,kBAAkB,GAAG,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG;QACrB,IAAI,CAAC,iBAAiB,GACpB,AAA2B,cAA3B,IAAI,CAAC,iBAAiB,GAAiB,YAAY;QACrD,IAAI,CAAC,iBAAiB,GAAG;YACvB,SAAS;YACT,OAAO;YACP,cAAc;YACd,SAAS,IAAI,CAAC,qBAAqB;YACnC,gBAAgB,IAAI,CAAC,mBAAmB;YACxC,UAAU,IAAI,CAAC,aAAa;QAC9B;QACA,IAAI,CAAC,aAAa,CAAC,KAAK;QACxB,IAAI,CAAC,gBAAgB;IACvB;IAEA,oBACEC,QAUC,EACK;QAEN,IAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,IAAI,IAAI,CAAC,iBAAiB,CAAC,YAAY,EACvE,IAAI,CAAC,iBAAiB,CAAC,OAAO,GAAG;QAEnC,IAAI,CAAC,uCAAuC,CAAC;QAC7C,IAAI,CAAC,cAAc,GAAGA,SAAS,cAAc;QAC7C,IAAI,CAAC,qBAAqB,GAAGA,SAAS,QAAQ,GAC1C;YAAE,GAAGA,SAAS,QAAQ;QAAC,IACvBjB;QACJ,IAAI,CAAC,iBAAiB,GAAG;YACvB,YAAYiB,SAAS,UAAU;YAC/B,OAAOA,SAAS,KAAK;YACrB,aAAaA,SAAS,WAAW;YACjC,SAASA,SAAS,OAAO;YACzB,UAAU,IAAI,CAAC,oBAAoB;QACrC;QACA,IAAI,CAAC,mBAAmB,GAAGA,SAAS,cAAc;QAClD,IAAI,CAAC,aAAa,GAAGA,SAAS,QAAQ;QACtC,IAAI,CAAC,0BAA0B;QAE/B,IACE,IAAI,CAAC,cAAc,IACnB,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,IAC7B,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAC/B;YACA,IAAI,CAAC,iBAAiB,GACpB,IAAI,CAAC,qBAAqB,EAAE,eAAe,YACvC,YACA;YACN,IAAI,CAAC,0BAA0B,GAC7B,AAA2D,YAA3D,OAAO,IAAI,CAAC,qBAAqB,EAAE,sBAC/B,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,GAC9CjB;QACR;IACF;IAEA,qBAAqBkB,OAAqC,EAAQ;QAChE,IAAI,CAAC,uCAAuC,CAAC;QAC7C,IAAI,CAAC,iBAAiB,GAAG;YACvB,GAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC;YAChCA;QACF;QACA,IAAI,CAAC,0BAA0B;IACjC;IAEA,mBAAmBC,QAAkC,EAAQ;QAC3D,IAAI,CAAC,uCAAuC,CAAC;QAC7C,IAAI,CAAC,qBAAqB,GAAGA,WAAW;YAAE,GAAGA,QAAQ;QAAC,IAAInB;QAC1D,IAAI,CAAC,gBAAgB;IACvB;IAEA,iBAAwC;QACtC,OAAOoB,iBAAiB;YACtB,YAAY,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;YAC5C,OAAO,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;YACvC,qBAAqB,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;YACrD,eACE,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,iBAAiB;YAC5D,sBACE,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,gBAAgBpB;YAC3D,SAAS,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;YACzC,UAAU,IAAI,CAAC,oBAAoB;YACnC,oBACE,AACA,cADA,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW;YAElD,gBAAgB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW;YACzD,YAAY,IAAI,CAAC,UAAU;QAC7B;IACF;IAYQ,yBAAkC;QACxC,MAAMqB,eAAe,IAAI,CAAC,cAAc,GACpCC,QACE,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,aAC9B,IAAI,CAAC,iBAAiB,CAAC,KAAK,IAEhCA,QAAQ,IAAI,CAAC,iBAAiB,CAAC,KAAK;QACxC,OAAOD,gBAAgB,CAAC,IAAI,CAAC,WAAW;IAC1C;IAEA,iBAGE;QACA,OAAO;YACL,WAAW,IAAI,CAAC,sBAAsB;YACtC,aAAa,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;YAC7C,UAAU;gBACR,GAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACpD;YACA,YAAY,IAAI,CAAC,iBAAiB;YAClC,qBAAqB,IAAI,CAAC,0BAA0B;QACtD;IACF;IAEQ,uBAAgD;QACtD,OAAO;YACL,GAAI,IAAI,CAAC,qBAAqB,IAAI,CAAC,CAAC;YACpC,GAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YAClD,kBAAkB,IAAI,CAAC,sBAAsB;YAC7C,oBAAoB,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE;YACpD,YAAY,IAAI,CAAC,iBAAiB;YAClC,GAAI,IAAI,CAAC,0BAA0B,GAC/B;gBAAE,qBAAqB,IAAI,CAAC,0BAA0B;YAAC,IACvD,CAAC,CAAC;QACR;IACF;IAEA,MAAc,cAAcE,QAA8B,EAAiB;QACzE,KAAK,MAAMC,WAAWD,YAAY,EAAE,CAClC,MAAMC,QAAQ,KAAK;IAEvB;IAEA,MAAc,aAAaD,QAA8B,EAAiB;QACxE,KAAK,MAAMC,WAAWD,YAAY,EAAE,CAClC,MAAMC,QAAQ,IAAI;IAEtB;IAEQ,wBAAmC;QACzC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAC/B,MAAM,IAAIxD,MAAM;QAGlB,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK;IACrC;IAEA,MAAc,oBAAoB,EAChCyD,uBAAuB,KAAK,EACO,GAAG,CAAC,CAAC,EAAiB;QACzD,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAC/B;QAGF,IAAI;YACF,IAAI,AAAgD,cAAhD,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAC7C,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,OAAO;QAE9C,EAAE,OAAOd,OAAO;YACdJ,QAAQ,IAAI,CAAC,gCAAgCI;QAC/C,SAAU;YAIR,IAAI,CAAC,cAAc,CAAC,MAAM;gBAAEc;YAAqB;YAEjD,IAAI,CAAC,YAAY,GAAG;QACtB;IACF;IAEA,MAAc,wBAAuC;QACnD,MAAMC,kBAAkB,IAAI,CAAC,iBAAiB,CAAC,OAAO;QACtD,MAAMC,mBAAmB,IAAI,CAAC,iBAAiB,CAAC,QAAQ;QACxD,MAAM,IAAI,CAAC,mBAAmB;QAC9B,MAAM,IAAI,CAAC,YAAY,CAACA;QAExB,IAAI,IAAI,CAAC,cAAc,EAAE,gBACvB,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,CAACD,mBAAmB1B;QAG9D,IAAI,CAAC,uBAAuB;IAC9B;IAEA,MAAc,oBACZ4B,OAAiC,EAClB;QACf,IAAI,CAACA,QAAQ,KAAK,IAAI,CAACA,QAAQ,YAAY,EACzC,MAAM,IAAI5D,MACR;QAIJ,MAAM6D,kBAAkBD,QAAQ,QAAQ,IAAI,IAAI,CAAC,aAAa;QAC9D,MAAM,IAAI,CAAC,aAAa,CAACC;QAEzB,IAAI;YACF,IAAI,CAAC,iBAAiB,GAAG;gBACvB,SAAS;oBACP,WAAW;oBACX,aAAaD,QAAQ,WAAW;oBAChC,UAAUA,QAAQ,QAAQ,GAAG;wBAAE,GAAGA,QAAQ,QAAQ;oBAAC,IAAI,CAAC;gBAC1D;gBACA,OAAOA,QAAQ,KAAK,IAAI;gBACxB,cAAcA,QAAQ,YAAY,IAAI;gBACtC,SAAS;oBACP,YAAYA,QAAQ,UAAU,IAAI,IAAI,CAAC,iBAAiB,EAAE;oBAC1D,OAAOA,QAAQ,KAAK,IAAI,IAAI,CAAC,iBAAiB,EAAE;oBAChD,aACEA,QAAQ,mBAAmB,IAAI,IAAI,CAAC,iBAAiB,EAAE;oBACzD,SAASA,QAAQ,OAAO,IAAI,IAAI,CAAC,iBAAiB,EAAE;oBACpD,UAAUA,QAAQ,QAAQ,GAAG;wBAAE,GAAGA,QAAQ,QAAQ;oBAAC,IAAI,CAAC;gBAC1D;gBACA,gBAAgBA,QAAQ,cAAc,IAAI,IAAI,CAAC,mBAAmB;gBAClE,UAAUC;YACZ;YACA,IAAI,CAAC,aAAa,CAAC,KAAK;YACxB,IAAI,CAAC,iBAAiB,GAAG;YACzB,IAAI,CAAC,0BAA0B,GAAG7B;YAClC,IAAI,CAAC,gBAAgB;QACvB,EAAE,OAAOW,OAAO;YACd,MAAM,IAAI,CAAC,YAAY,CAACkB,iBAAiB,KAAK,CAAC,KAAO;YACtD,IAAI,CAAC,uBAAuB;YAC5B,MAAMlB;QACR;IACF;IAEA,MAAc,sBACZmB,KAA+B,EACS;QACxC,IAAI,CAAC,IAAI,CAAC,cAAc,EACtB,OAAO;QAGT,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,GACrC,IAAI,CAAC,cAAc,CAAC,cAAc,CAACA,SACnC;IACN;IAEA,MAAc,oBAAwD;QACpE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,aACxB,OAAO,EAAE;QAGX,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW;IACxC;IAyBA,IAAI,MAA2B;QAC7B,OAAO,IAAI,CAAC,IAAI;IAClB;IAMQ,gBAAsB;QAC5B,IAAI,IAAI,CAAC,YAAY,EAAE;QAGvB,IAAI,CAAC,IAAI,CAAC,GAAG,CAACC,QAAQ,IAAI,CAAC;YAAE,OAAO;QAAO;QAG3C,IAAI,CAAC,IAAI,CAAC,GAAG,CACX,CAAC3B,KAAc4B,MAAgB1B;YAC7B,MAAM,EAAE2B,OAAO,EAAE,GAAG7B,IAAI,IAAI,IAAI,CAAC;YACjC,IACE,IAAI,CAAC,iBAAiB,CAAC,KAAK,IAC5B6B,WACA,mBAAmB,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,SAAS,IACzD,AACE,cADF,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,aAAa,EAE3D;gBACA,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,aAAa,CAACA;gBACrD1B,QAAQ,GAAG,CAAC;YACd;YACAD;QACF;QAOF,IAAI,CAAC,WAAW;QAGhB,IAAI,CAAC,iBAAiB;QAGtB,IAAI,CAAC,IAAI,CAAC,GAAG,CAACJ;QAEd,IAAI,CAAC,YAAY,GAAG;IACtB;IAEA,gBAAgBD,IAAY,EAAE;QAG5B,IAAI,CAAC,kBAAkB,IAAI,CAACA,OAC1B,MAAM,IAAIjC,MAAM;QAElB,MAAMkE,WAAWvE,KAAK,IAAI,CAAC,MAAM,EAAE,GAAGsC,KAAK,KAAK,CAAC;QAEjD,MAAMkC,eAAeC,2BAAQF;QAC7B,MAAMG,iBAAiBD,2BAAQ,IAAI,CAAC,MAAM;QAC1C,IAAI,CAACD,aAAa,UAAU,CAACE,iBAC3B,MAAM,IAAIrE,MAAM;QAElB,OAAOkE;IACT;IAEA,gBAAgBjC,IAAY,EAAEgC,OAAe,EAAE;QAC7C,MAAMK,UAAU,IAAI,CAAC,eAAe,CAACrC;QACrCM,QAAQ,GAAG,CAAC,CAAC,mBAAmB,EAAE+B,SAAS;QAC3CC,cAAcD,SAASL;QACvB,OAAOK;IACT;IAWA,MAAc,cAAc,EAC1Bb,uBAAuB,KAAK,EACO,GAAG,CAAC,CAAC,EAAiB;QACzD,IAAI,CAAC,WAAW,GAAG;QACnBlB,QAAQ,GAAG,CAAC;QAEZ,MAAM,IAAI,CAAC,mBAAmB,CAAC;YAAEkB;QAAqB;QAGtD,IAAI,IAAI,CAAC,iBAAiB,CAAC,YAAY,EACrC,IAAI;YACF,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,YAAY,IAAI;gBAC/DA;YACF;YACA,IAAI,CAAC,WAAW,GAAG;YACnBlB,QAAQ,GAAG,CAAC;QACd,EAAE,OAAOI,OAAO;YACd,IAAI,CAAC,WAAW,GAAG;YACnBJ,QAAQ,KAAK,CAAC,6BAA6BI;YAC3C,MAAMA;QACR;aACK;YACL,IAAI,CAAC,WAAW,GAAG;YACnBJ,QAAQ,IAAI,CACV;QAEJ;IACF;IAEA,MAAc,oCACZI,KAAc,EACd6B,MAAc,EACa;QAC3B,IACE,CAAC,IAAI,CAAC,iBAAiB,CAAC,YAAY,IACpC,CAAC9B,8BAA8BC,QAE/B,OAAO;QAGT7C,WAAW,CAAC,8BAA8B,EAAE0E,OAAO,CAAC,CAAC,EAAE7B;QACvD,IAAI;YACF,IAAI,CAAC,aAAa,CAAC,KAAK;YACxB,MAAM,IAAI,CAAC,aAAa;YACxB,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK;QACrC,EAAE,OAAO8B,eAAe;YACtB3E,WACE,CAAC,qCAAqC,EAAE0E,OAAO,CAAC,CAAC,EACjDC;YAEF,OAAO;QACT;IACF;IAEQ,mBACN3B,KAAgB,EAChB9B,UAAkB,EACiB;QACnC,OAAQ8B,MAAM,SAAS,CAAC,WAAW,GAA+B,IAAI,CACpE,CAAC4B,QAAUA,MAAM,IAAI,KAAK1D;IAE9B;IAEQ,kCACN8B,KAAgB,EAChB9B,UAAkB,EACyB;QAC3C,OACEA,AAAe,WAAfA,cACA,AACE,cADF,OAAQ8B,MAAM,SAAS,CAA4B,WAAW;IAGlE;IAEA,MAAc,+BACZA,KAAgB,EAChB9B,UAAuC,EACxB;QACf,OAAQA;YACN,KAAK;gBACH,MAAO8B,MAAM,SAAS,CAA4B,WAAW;gBAC7D;QACJ;IACF;IAEA,MAAc,kBACZA,KAAgB,EAChB9B,UAAkB,EAClBG,MAA+B,EAChB;QACf,IAAI,IAAI,CAAC,iCAAiC,CAAC2B,OAAO9B,aAAa,YAC7D,MAAM,IAAI,CAAC,8BAA8B,CAAC8B,OAAO9B;QAInD,MAAM2D,SAAS,IAAI,CAAC,kBAAkB,CAAC7B,OAAO9B;QAC9C,IAAI,CAAC2D,UAAU,AAAuB,cAAvB,OAAOA,OAAO,IAAI,EAC/B,MAAM,IAAI3E,MACR,CAAC,QAAQ,EAAEgB,WAAW,wCAAwC,CAAC;QAInE,MAAM2D,OAAO,IAAI,CAACxD,QAAQU,4BAA4Bb,YAAYG;IACpE;IAKQ,cAAoB;QAC1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,OAAOiB,KAAcC;YAC5CA,IAAI,IAAI,CAAC;gBACP,QAAQ;gBACR,IAAI,IAAI,CAAC,EAAE;YACb;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,OAAOuC,MAAevC;YAC9CA,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc;QAC9B;QAEA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,kBAAkB,OAAOD,KAAcC;YACnD,IAAI;gBACF,MAAMwC,QAAQ,MAAM,IAAI,CAAC,qBAAqB,CAC5CpG,OAAO,WAAW,CAChBA,OAAO,OAAO,CAAC2D,IAAI,KAAK,EAAE,MAAM,CAC9B,CAAC,GAAGjC,MAAM,GAAK,AAAiB,YAAjB,OAAOA;gBAI5B,IAAI,CAAC0E,OACH,OAAOxC,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAO;gBACT;gBAGF,MAAMyC,UAAU,MAAM,IAAI,CAAC,iBAAiB;gBAC5CzC,IAAI,IAAI,CAAC;oBACP,GAAGwC,KAAK;oBACR,SAASC,QAAQ,MAAM,GAAG,IAAIA,UAAUD,MAAM,OAAO;gBACvD;YACF,EAAE,OAAOlC,OAAO;gBACdN,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBACnB,OACEM,iBAAiB3C,QACb2C,MAAM,OAAO,GACb;gBACR;YACF;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,oBAAoB,OAAOiC,MAAevC;YACtD,IAAI;gBACFA,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,iBAAiB;YACvC,EAAE,OAAOM,OAAO;gBACdN,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBACnB,OACEM,iBAAiB3C,QACb2C,MAAM,OAAO,GACb;gBACR;YACF;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,OAAOP,KAAcC;YAC9C,IAAI,CAAC,IAAI,CAAC,cAAc,EACtB,OAAOA,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAGF,IAAI,IAAI,CAAC,aAAa,EACpB,OAAOA,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAGF,IAAI;gBACF,MAAM,IAAI,CAAC,qBAAqB;gBAChC,MAAM0C,UAAU,MAAM,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC3C,IAAI,IAAI,IAAI,CAAC;gBACrE,MAAM,IAAI,CAAC,mBAAmB,CAAC2C;gBAE/B,IACE,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,IAC7B,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAEnC,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,YAAY;gBAG/D,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE;oBAC5D,IAAI,CAAC,YAAY,GAAG;oBACpB,MAAM,IAAI,CAAC,aAAa;gBAC1B;gBAEA1C,IAAI,IAAI,CAAC;oBACP,SAAS,IAAI,CAAC,cAAc;oBAC5B,aAAa,IAAI,CAAC,cAAc;gBAClC;YACF,EAAE,OAAOM,OAAO;gBACd,MAAMqC,wBAAwB,IAAI,CAAC,iBAAiB,CAAC,OAAO,GACxD,IAAI,CAAC,iBAAiB,CAAC,QAAQ,GAC/BhD;gBACJ,MAAM,IAAI,CAAC,mBAAmB;gBAC9B,MAAM,IAAI,CAAC,YAAY,CAACgD,uBAAuB,KAAK,CAAC,KAAO;gBAC5D,IAAI,CAAC,uBAAuB;gBAC5B3C,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBACnB,OACEM,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC7C;YACF;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,OAAOiC,MAAevC;YACjD,IAAI,IAAI,CAAC,aAAa,EACpB,OAAOA,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAGF,IAAI;gBACF,MAAM,IAAI,CAAC,qBAAqB;gBAChCA,IAAI,IAAI,CAAC;oBACP,SAAS,IAAI,CAAC,cAAc;oBAC5B,aAAa,IAAI,CAAC,cAAc;gBAClC;YACF,EAAE,OAAOM,OAAO;gBACdN,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBACnB,OACEM,iBAAiB3C,QACb2C,MAAM,OAAO,GACb;gBACR;YACF;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,kBAAkB,OAAOP,KAAcC;YACnD,MAAM,EAAEJ,IAAI,EAAE,GAAGG,IAAI,MAAM;YAC3B,IAAI6C;YACJ,IAAI;gBACFA,cAAc,IAAI,CAAC,eAAe,CAAChD;YACrC,EAAE,OAAM;gBACN,OAAOI,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAO;gBACT;YACF;YAEA,IAAI,CAAC6C,WAAWD,cACd,OAAO5C,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAGF,MAAM4B,UAAUkB,aAAaF,aAAa;YAC1C5C,IAAI,IAAI,CAAC;gBACP4B;YACF;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,GAAG,CACX,6BACA,OAAO7B,KAAcC;YACnB,MAAM,EAAE+C,SAAS,EAAE,GAAGhD,IAAI,MAAM;YAChC,MAAMiD,gBAAgB,IAAI,CAAC,kBAAkB,CAACD,UAAU,IAAI;YAE5D/C,IAAI,IAAI,CAAC;gBACPgD;YACF;QACF;QAGF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,OAAOjD,KAAcC;YACnD,IAAI;gBACF,MAAMS,QAAQ,IAAI,CAAC,qBAAqB;gBACxC,IAAIwC,cAAc,EAAE;gBAEpBA,cAAcxC,MAAM,SAAS,CAAC,WAAW;gBAGzC,MAAMyC,uBAAuBD,YAAY,GAAG,CAAC,CAACX;oBAC5C,IAAIA,UAAU,AAAkB,YAAlB,OAAOA,UAAuB,iBAAiBA,QAAQ;wBACnE,MAAMa,cAAcb;wBAIpB,IACEa,YAAY,WAAW,IACvB,AAAmC,YAAnC,OAAOA,YAAY,WAAW,EAC9B;4BAEA,IAAIC,kBAAkB;4BAEtB,IAAI;gCAEF,IACED,YAAY,WAAW,CAAC,KAAK,IAC7B,AAAyC,YAAzC,OAAOA,YAAY,WAAW,CAAC,KAAK,EACpC;oCACA,MAAMtG,WAAWsG,YAAY,WAAW,CAAC,KAAK;oCAI9C,MAAMrG,kBAAuC,CAAC;oCAC9C,KAAK,MAAM,CAACuG,KAAK7G,MAAM,IAAIJ,OAAO,OAAO,CAACS,UACxCC,eAAe,CAACuG,IAAI,GAAG9G,kBAAkBC;oCAE3C4G,kBAAkB;wCAChB,MAAM;wCACN,OAAOtG;oCACT;gCACF;4BACF,EAAE,OAAOwG,GAAG;gCACV,MAAMC,aACJ,UAAUJ,eAAe,AAA4B,YAA5B,OAAOA,YAAY,IAAI,GAC5CA,YAAY,IAAI,GAChB;gCACNjD,QAAQ,IAAI,CACV,6CACAqD,YACAD;4BAEJ;4BAEA,OAAO;gCACL,GAAGH,WAAW;gCACd,aAAaC;4BACf;wBACF;oBACF;oBACA,OAAOd;gBACT;gBAEAtC,IAAI,IAAI,CAACkD;YACX,EAAE,OAAO5C,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CAAC,+BAA+BI;gBAC7CN,IAAI,MAAM,CAACG,AAAiB,wBAAjBA,eAAuC,MAAM,KAAK,IAAI,CAAC;oBAChE,OAAOA;gBACT;YACF;QACF;QAIA,IAAI,CAAC,IAAI,CAAC,IAAI,CACZ,4BACA,OAAOJ,KAAcC;YACnB,MAAM4B,UAAU7B,IAAI,IAAI,CAAC,OAAO;YAEhC,IAAI,CAAC6B,SACH,OAAO5B,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAGF,MAAM+C,YAAYnD;YAClB,IAAI,CAAC,eAAe,CAACmD,WAAWnB;YAChC,OAAO5B,IAAI,IAAI,CAAC;gBACd,UAAU,CAAC,YAAY,EAAE+C,WAAW;gBACpC,MAAMA;YACR;QACF;QAGF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,OAAOhD,KAAcC;YAC9C,IAAIS;YACJ,IAAI;gBACFA,QAAQ,IAAI,CAAC,qBAAqB;YACpC,EAAE,OAAOH,OAAO;gBACd,OAAON,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAOM,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAClD;YACF;YAEA,MAAM,EACJkD,IAAI,EACJC,MAAM,EACN3E,MAAM,EACNiE,SAAS,EACTW,UAAU,EACVC,SAAS,EACTC,kBAAkB,EAClBC,WAAW,EACXC,aAAa,EACd,GAAG/D,IAAI,IAAI;YAEZ,IAAI,CAACyD,MACH,OAAOxD,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAIF,IAAI,IAAI,CAAC,iBAAiB,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,EAAE;gBAC5D,IAAI,CAAC,YAAY,GAAG;gBACpB,IAAI,CAAC,WAAW,GAAG;gBACnBE,QAAQ,GAAG,CAAC;gBACZ,IAAI;oBACF,MAAM,IAAI,CAAC,mBAAmB;oBAC9B,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,YAAY;oBAC7DO,QAAQ,IAAI,CAAC,qBAAqB;oBAClC,IAAI,CAAC,WAAW,GAAG;oBACnBP,QAAQ,GAAG,CAAC;gBACd,EAAE,OAAOI,OAAO;oBACd,IAAI,CAAC,WAAW,GAAG;oBACnBJ,QAAQ,KAAK,CAAC,6BAA6BI;oBAC3C,OAAON,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;wBAC1B,OAAO,CAAC,wBAAwB,EAAEM,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG,iBAAiB;oBAC9F;gBACF;YACF;YAGA,IAAIwD,eAAe;gBACjB,MAAMC,QAAQtD,MAAM,SAAS;gBAG7BsD,MAAM,OAAO,GAAG;oBACd,GAAIA,MAAM,OAAO,IAAI,CAAC,CAAC;oBACvB,GAAGD,aAAa;gBAClB;YACF;YAGA,IAAI,IAAI,CAAC,aAAa,EACpB,OAAO9D,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;gBACP,eAAe,IAAI,CAAC,aAAa;YACnC;YAIF,IAAI+C,WAAW;gBACb,IAAI,CAAC,aAAa,GAAGA;gBACrB,IAAI,CAAC,kBAAkB,CAACA,UAAU,GAAG;gBAGrCtC,MAAM,YAAY,GAAG,CAACuD,OAAehB;oBACnC,IAAIA,eAEF,IAAI,CAAC,kBAAkB,CAACD,UAAU,GAAGC;gBAEzC;YACF;YAEA,MAAMiB,WAMF;gBACF,QAAQ;gBACR,MAAM;gBACN,OAAO;gBACP,YAAY;gBACZlB;YACF;YAEA,MAAMmB,YAAYC,KAAK,GAAG;YAC1B,IAAI;gBACF,MAAM,IAAI,CAAC,iBAAiB,CAAC,cAAc,EAAE;gBAG7C,MAAMlB,cAAcxC,MAAM,SAAS,CAAC,WAAW;gBAG/C,MAAM3C,QAAQ;oBACZ0F;oBACAC;oBACA3E;gBACF;gBAEAmF,SAAS,MAAM,GAAG,MAAMG,cAAc3D,OAAO+C,MAAMP,aAAanF,OAAO;oBACrE4F;oBACAC;oBACAC;oBACAC;oBACAC;gBACF;YACF,EAAE,OAAOxD,OAAgB;gBACvB2D,SAAS,KAAK,GAAGI,mBAAmB/D;YACtC,SAAU;gBACR,IAAI;oBACF,MAAM,IAAI,CAAC,iBAAiB,CAAC,cAAc,EAAE;gBAC/C,EAAE,OAAOgE,WAAW;oBAClBpE,QAAQ,KAAK,CAAC,uCAAuCoE;gBACvD;YACF;YAEA,IAAI;gBACF,MAAMC,aAAa9D,MAAM,cAAc,CAAC;oBACtC,mBAAmB;gBACrB;gBACA,IAAI8D,YAAY;oBACd,MAAMC,cAAcC,iBAAiB,oBAAoB,CAACF;oBAE1DN,SAAS,IAAI,GAAGO,YAAY,UAAU,EAAE,CAAC,EAAE,IAAI;gBACjD,OACEP,SAAS,IAAI,GAAG;gBAElBA,SAAS,UAAU,GACjBxD,MAAM,gBAAgB,CAAC;oBAAE,mBAAmB;gBAAK,MAAM;gBAEzDA,MAAM,mBAAmB;gBACzBA,MAAM,SAAS;YACjB,EAAE,OAAOH,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CACX,CAAC,kCAAkC,EAAE6C,UAAU,EAAE,EAAE5C,cAAc;YAErE,SAAU,CACV;YAEAH,IAAI,IAAI,CAACiE;YACT,MAAMS,WAAWP,KAAK,GAAG,KAAKD;YAE9B,IAAID,SAAS,KAAK,EAChB/D,QAAQ,KAAK,CACX,CAAC,4BAA4B,EAAEwE,SAAS,eAAe,EAAE3B,UAAU,EAAE,EAAEkB,SAAS,KAAK,EAAE;iBAGzF/D,QAAQ,GAAG,CACT,CAAC,0BAA0B,EAAEwE,SAAS,eAAe,EAAE3B,WAAW;YAKtE,IAAIA,WAAW;gBACb,OAAO,IAAI,CAAC,kBAAkB,CAACA,UAAU;gBAEzC,IAAI,IAAI,CAAC,aAAa,KAAKA,WACzB,IAAI,CAAC,aAAa,GAAG;YAEzB;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,IAAI,CACZ,sBACA,OAAOhD,KAAcC;YACnB,MAAM,EAAE+C,SAAS,EAAE,GAAGhD,IAAI,MAAM;YAEhC,IAAI,CAACgD,WACH,OAAO/C,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAGF,IAAI;gBACF,MAAMS,QAAQ,IAAI,CAAC,qBAAqB;gBAExC,IAAI,IAAI,CAAC,aAAa,KAAKsC,WACzB,OAAO/C,IAAI,IAAI,CAAC;oBACd,QAAQ;oBACR,SAAS;gBACX;gBAGFE,QAAQ,GAAG,CAAC,CAAC,iBAAiB,EAAE6C,WAAW;gBAG3C,IAAI4B,OAAY;gBAChB,IAAIC,aAA4B;gBAEhC,IAAI;oBACF,MAAML,aAAa9D,MAAM,cAAc,GAAG;wBACxC,mBAAmB;oBACrB;oBACA,IAAI8D,YAAY;wBACd,MAAMC,cACJC,iBAAiB,oBAAoB,CAACF;wBAExCI,OAAOH,YAAY,UAAU,EAAE,CAAC,EAAE,IAAI;oBACxC;oBAEAI,aACEnE,MAAM,gBAAgB,GAAG;wBACvB,mBAAmB;oBACrB,MAAM;gBACV,EAAE,OAAOH,OAAgB;oBACvBJ,QAAQ,IAAI,CAAC,+CAA+CI;gBAC9D;gBAOA,IAAI;oBACF,MAAM,IAAI,CAAC,aAAa,CAAC;wBAAE,sBAAsB;oBAAK;gBACxD,EAAE,OAAOA,OAAO;oBACdJ,QAAQ,IAAI,CAAC,2CAA2CI;gBAC1D;gBAGA,OAAO,IAAI,CAAC,kBAAkB,CAACyC,UAAU;gBACzC,IAAI,CAAC,aAAa,GAAG;gBAErB/C,IAAI,IAAI,CAAC;oBACP,QAAQ;oBACR,SAAS;oBACT2E;oBACAC;gBACF;YACF,EAAE,OAAOtE,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CAAC,CAAC,kBAAkB,EAAEC,cAAc;gBACjDH,IAAI,MAAM,CAACG,AAAiB,wBAAjBA,eAAuC,MAAM,KAAK,IAAI,CAAC;oBAChE,OAAO,CAAC,kBAAkB,EAAEA,cAAc;gBAC5C;YACF;QACF;QAIF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,OAAOoC,MAAevC;YACjD,IAAI;gBACF,IAAIS,QAAQ,IAAI,CAAC,qBAAqB;gBAEtC,IAAI,AAA4C,cAA5C,OAAOA,MAAM,SAAS,CAAC,gBAAgB,EACzC,OAAOT,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAO;gBACT;gBAGF,IAAI6E;gBACJ,IAAI;oBACFA,aAAa,MAAMpE,MAAM,SAAS,CAAC,gBAAgB;gBACrD,EAAE,OAAOH,OAAO;oBACd,MAAMwE,iBAAiB,MAAM,IAAI,CAAC,mCAAmC,CACnExE,OACA;oBAEF,IACE,CAACwE,kBACD,AAAqD,cAArD,OAAOA,eAAe,SAAS,CAAC,gBAAgB,EAEhD,MAAMxE;oBAERG,QAAQqE;oBACRD,aAAa,MAAMpE,MAAM,SAAS,CAAC,gBAAgB;gBACrD;gBAEAT,IAAI,IAAI,CAAC;oBACP6E;oBACA,WAAWV,KAAK,GAAG;gBACrB;YACF,EAAE,OAAO7D,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3C,MAAMyE,aAAa5E,AAAiB,wBAAjBA,eAAuC,MAAM;gBAChE,IAAI4E,AAAe,QAAfA,YACF7E,QAAQ,KAAK,CAAC,CAAC,2BAA2B,EAAEC,cAAc;gBAE5DH,IAAI,MAAM,CAAC+E,YAAY,IAAI,CAAC;oBAC1B,OAAO,CAAC,2BAA2B,EAAE5E,cAAc;gBACrD;YACF;QACF;QAKA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,OAAOJ,KAAcC;YAC3C,MAAMS,QAAQ,IAAI,CAAC,iBAAiB,CAAC,KAAK;YAC1C,IAAI,CAACA,OACH,OAAOT,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAAE,OAAO;YAAoB;YAE3D,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAACD,KAAKC;QACtC;QAGA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,OAAOuC,MAAevC;YACrD,IAAI;gBACF,MAAMgF,cAAc,IAAI,CAAC,cAAc;gBACvC,MAAMvE,QAAQ,IAAI,CAAC,iBAAiB,CAAC,KAAK;gBAC1C,IAAIwE;gBACJ,IAAIC;gBACJ,IAAIC;gBACJ,IAAI,AAAkC,cAAlC,OAAO1E,OAAO,WAAW,MAC3B,IAAI;oBACFwE,OAAO,MAAMxE,MAAM,SAAS,CAAC,IAAI;gBACnC,EAAE,OAAOH,OAAO;oBACd/C,gBAAgB,4BAA4B+C;gBAC9C;gBAEF,IAAI,AAA6C,cAA7C,OAAOG,OAAO,WAAW,iBAC3B,IAAI;oBACFyE,kBAAkB,MAAMzE,MAAM,SAAS,CAAC,eAAe;gBACzD,EAAE,OAAOH,OAAO;oBACd/C,gBAAgB,uCAAuC+C;gBACzD;gBAEF,IAAI,AAAyC,cAAzC,OAAOG,OAAO,WAAW,aAC3B,IAAI;oBACF,MAAM2E,UAAU3E,MAAM,SAAS,CAAC,WAAW;oBAC3C0E,cAAcvI,MAAM,OAAO,CAACwI,WACxBA,QACG,GAAG,CAAC,CAAC9C,SAAWA,QAAQ,MACxB,MAAM,CAAC,CAAC+C,OAAyB,AAAgB,YAAhB,OAAOA,QAC3C1F;gBACN,EAAE,OAAOW,OAAO;oBACd/C,gBAAgB,mCAAmC+C;gBACrD;gBAGFN,IAAI,IAAI,CAAC;oBACP,MAAMgF,YAAY,SAAS,CAAC,IAAI;oBAChC,aAAaA,YAAY,SAAS,CAAC,WAAW;oBAC9C,GAAIC,OAAO;wBAAEA;oBAAK,IAAI,CAAC,CAAC;oBACxB,GAAIC,kBAAkB;wBAAEA;oBAAgB,IAAI,CAAC,CAAC;oBAC9C,GAAIC,cAAc;wBAAEA;oBAAY,IAAI,CAAC,CAAC;gBACxC;YACF,EAAE,OAAO7E,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CAAC,CAAC,8BAA8B,EAAEC,cAAc;gBAC7DH,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBACnB,OAAO,CAAC,8BAA8B,EAAEG,cAAc;gBACxD;YACF;QACF;QAMA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,OAAOJ,KAAcC;YAC/C,IAAIS;YACJ,IAAI;gBACFA,QAAQ,IAAI,CAAC,qBAAqB;YACpC,EAAE,OAAOH,OAAO;gBACd,OAAON,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAOM,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAClD;YACF;YAEA,MAAM,EAAE3B,UAAU,EAAE,GAAGoB,IAAI,IAAI,IAAI,CAAC;YACpC,IAAI,AAAsB,YAAtB,OAAOpB,cAA2B,CAACA,YACrC,OAAOqB,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAGF,IAAI;gBACF,MAAMsF,kBAAkB7E,MAAM,SAAS,CAAC,eAAe;gBACvD,IAAI6E,iBAAiB;oBACnB,MAAMC,gBAAgBD,iBAAiBvF,IAAI,IAAI,IAAI,CAAC,GAAG,IACrDU,MAAM,SAAS,CAAC,IAAI;oBAEtBT,IAAI,IAAI,CAAC,CAAC;oBACV;gBACF;gBAEA,IACE,CAAC,IAAI,CAAC,kBAAkB,CAACS,OAAO9B,eAChC,CAAC,IAAI,CAAC,iCAAiC,CAAC8B,OAAO9B,aAE/C,OAAOqB,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAOtB,4BAA4BC,cAC/B,mDACA,CAAC,QAAQ,EAAEA,WAAW,wCAAwC,CAAC;gBACrE;gBAGF,MAAMG,SAASM,oBAAoBT,YAAYoB,IAAI,IAAI,IAAI,CAAC;gBAC5D,MAAM,IAAI,CAAC,iBAAiB,CAACU,OAAO9B,YAAYG;gBAChDkB,IAAI,IAAI,CAAC,CAAC;YACZ,EAAE,OAAOM,OAAgB;gBACvB,IAAIA,iBAAiBkF,mBACnB,OAAOxF,IAAI,MAAM,CAACM,MAAM,UAAU,EAAE,IAAI,CAAC;oBAAE,OAAOA,MAAM,OAAO;gBAAC;gBAElE,IAAIA,iBAAiB5C,+BACnB,OAAOsC,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAAE,OAAOM,MAAM,OAAO;gBAAC;gBAGrD,MAAMwE,iBAAiB,MAAM,IAAI,CAAC,mCAAmC,CACnExE,OACA,CAAC,wBAAwB,EAAE3B,WAAW,CAAC,CAAC;gBAE1C,IAAImG,gBACF,OAAO9E,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OACE;gBACJ;gBAGF,MAAMG,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CACX,CAAC,+BAA+B,EAAEvB,WAAW,GAAG,EAAEwB,cAAc;gBAElEH,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAAE,OAAOG;gBAAa;YAC7C;QACF;QAEA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,OAAOoC,MAAevC;YACnD,IAAI;gBACFA,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc;YAC9B,EAAE,OAAOM,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CAAC,CAAC,4BAA4B,EAAEC,cAAc;gBAC3DH,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBACnB,OAAO,CAAC,4BAA4B,EAAEG,cAAc;gBACtD;YACF;QACF;QAEA,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,OAAOJ,KAAcC;YAC5C,MAAM,EAAE9D,QAAQ,EAAE,GAAG6D,IAAI,IAAI;YAE7B,IAAI,CAAC7D,YAAY,AAAoB,YAApB,OAAOA,UACtB,OAAO8D,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;gBAC1B,OAAO;YACT;YAGF,IAAI5D,AAAiC,MAAjCA,OAAO,IAAI,CAACF,UAAU,MAAM,EAC9B,OAAO8D,IAAI,IAAI,CAAC;gBACd,QAAQ;gBACR,SAAS;YACX;YAGF,MAAMyF,sBAAsBxJ,2BAA2BC;YACvD,MAAMwJ,gBAAgBD,wBAAwB,IAAI,CAAC,sBAAsB;YAEzE,IAAI;gBACF,IAAIC,eAAe;oBACjBC,iBAAiBzJ;oBACjB,IAAI,CAAC,sBAAsB,GAAGuJ;oBAC9B,IAAI,CAAC,YAAY,GAAGxE,QAAQ,IAAI,CAAC,iBAAiB,CAAC,KAAK;gBAC1D;YACF,EAAE,OAAOX,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CAAC,CAAC,4BAA4B,EAAEC,cAAc;gBAC3D,OAAOH,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAO,CAAC,4BAA4B,EAAEG,cAAc;gBACtD;YACF;YAEA,IAAI,CAACuF,eACH,OAAO1F,IAAI,IAAI,CAAC;gBACd,QAAQ;gBACR,SAAS;YACX;YAIF,IAAI;gBACF4F,yBAAyB,cAAc,CAAC;YAC1C,EAAE,OAAOtF,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CAAC,CAAC,6BAA6B,EAAEC,cAAc;gBAC5D,OAAOH,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAOG;gBACT;YACF;YAEA,OAAOH,IAAI,IAAI,CAAC;gBACd,QAAQ;gBACR,SAAS,IAAI,CAAC,YAAY,GACtB,kEACA;YACN;QACF;QAEA,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,sBACA,OAAOuC,MAAevC;YACpB,IAAI;gBACF,MAAMrD,SAAS,MAAMkJ,oBAAoB;oBACvC,oBACED,yBAAyB,cAAc,CAAC;oBAC1C,qBACEA,yBAAyB,cAAc,CAAC;oBAC1C,oBACEA,yBAAyB,cAAc,CAAC;gBAC5C;gBACA,OAAO5F,IAAI,IAAI,CAACrD;YAClB,EAAE,OAAO2D,OAAgB;gBACvB,MAAMH,eACJG,iBAAiB3C,QAAQ2C,MAAM,OAAO,GAAG;gBAC3CJ,QAAQ,KAAK,CAAC,CAAC,0BAA0B,EAAEC,cAAc;gBACzD,OAAOH,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAC1B,OAAOG;gBACT;YACF;QACF;IAEJ;IAKQ,oBAA0B;QAEhC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAACoC,MAAevC;YACjC,IAAI,CAAC,kBAAkB,CAACA;QAC1B;QAEA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAACuC,MAAevC;YAC3C,IAAI,CAAC,kBAAkB,CAACA;QAC1B;QAGA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC0B,OAAO,CAAPA,SAAc,CAAC,IAAI,CAAC,UAAU;QAG5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAACa,MAAevC;YACjC,IAAI,CAAC,kBAAkB,CAACA;QAC1B;IACF;IAKQ,mBAAmBA,GAAa,EAAQ;QAC9C,IAAI;YACF,MAAM8F,WAAWxI,KAAK,IAAI,CAAC,UAAU,EAAE;YACvC,IAAIyI,OAAOjD,aAAagD,UAAU;YAElC,MAAME,aAAa,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,GAAI;YAGnD,MAAMC,eAAe,CAAC;;+BAEG,EAAED,WAAW;;MAEtC,CAAC;YAGDD,OAAOA,KAAK,OAAO,CAAC,WAAW,GAAGE,aAAa,OAAO,CAAC;YAEvDjG,IAAI,SAAS,CAAC,gBAAgB;YAC9BA,IAAI,IAAI,CAAC+F;QACX,EAAE,OAAOzF,OAAO;YACdJ,QAAQ,KAAK,CAAC,kCAAkCI;YAChDN,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;QACvB;IACF;IAKA,MAAM,OAAOkG,IAAa,EAA6B;QAErD,IAAI,IAAI,CAAC,iBAAiB,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YAC/DhG,QAAQ,GAAG,CAAC;YACZ,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,YAAY;YAC7D,IAAI,CAAC,iBAAiB,CAAC,OAAO,GAAG;gBAC/B,WAAW;gBACX,UAAU,CAAC;YACb;YACA,IAAI,CAAC,iBAAiB,GAAG;YACzB,IAAI,CAAC,gBAAgB;YACrBA,QAAQ,GAAG,CAAC;QACd;QAGA,IAAI,CAAC,aAAa;QAElB,IAAI,CAAC,IAAI,GAAGgG,QAAQnK;QAEpB,OAAO,IAAIoK,QAAQ,CAACpE;YAClB,MAAMqE,aAAa,IAAI,CAAC,IAAI,IAAIrK;YAChC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAACqK,YAAY,WAAW;gBACpDrE,QAAQ,IAAI;YACd;QACF;IACF;IAKA,MAAM,QAAuB;QAC3B,MAAM,IAAI,CAAC,qBAAqB,GAAG,KAAK,CAAC,CAACzB;YACxCJ,QAAQ,IAAI,CAAC,sDAAsDI;QACrE;QACA,IAAI,CAAC,aAAa,CAAC,QAAQ;QAE3B,OAAO,IAAI6F,QAAQ,CAACpE,SAASsE;YAC3B,IAAI,IAAI,CAAC,MAAM,EAAE;gBACf,IAAI,CAAC,kBAAkB,GAAG,CAAC;gBAG3B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC/F;oBACjB,IAAIA,OACF+F,OAAO/F;yBACF;wBACL,IAAI,CAAC,MAAM,GAAGX;wBACdoC;oBACF;gBACF;YACF,OACEA;QAEJ;IACF;IAv6CA,YACEtB,KAAkE,EAClE6F,aAAajJ,WAAW,EACxBkJ,EAAW,CACX;QA/EF,uBAAQ,QAAR;QACA;QACA;QACA;QACA;QACA;QACA;QAMA;QAEA,uBAAQ,gBAAe;QAEvB,uBAAiB,iBAAgB,IAAIC,mBAAmB;YACtD,cAAc,IAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW;YAC7D,oBAAoB,IAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,aAAa;YACrE,gBAAgB,IACd,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC,gBAAgB;YACzD,mBAAmB,IACjB,AACA,cADA,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW;YAElD,cAAc,IAAM,IAAI,CAAC,WAAW;YACpC,yBAAyB,OAAOlG,OAAO6B,SACpC,OAAM,IAAI,CAAC,mCAAmC,CAAC7B,OAAO6B,OAAM,GACzD,aAAa;QACrB;QAEA,uBAAQ,kBAAR;QACA,uBAAQ,qBAAsD;QAC9D,uBAAQ,8BAAR;QAGA,uBAAQ,iBAA+B;QAGvC,uBAAQ,eAAc;QAGtB,uBAAQ,gBAAe;QACvB,uBAAQ,0BAAwC;QAChD,uBAAQ,qBAAR;QACA,uBAAQ,yBAAR;QACA,uBAAQ,uBAAR;QACA,uBAAQ,iBAAR;QACA,uBAAQ,qBAAgD;YACtD,SAAS;YACT,OAAO;YACP,cAAc;YACd,SAASxC;YACT,gBAAgBA;YAChB,UAAUA;QACZ;QA0BE,IAAI,CAAC,IAAI,GAAG+B;QACZ,IAAI,CAAC,MAAM,GAAG+E;QACd,IAAI,CAAC,UAAU,GAAGH;QAClB,IAAI,CAAC,kBAAkB,GAAG,CAAC;QAE3B,IAAI,CAAC,EAAE,GAAGC,MAAM3G;QAGhB,IAAI,AAAiB,cAAjB,OAAOa,OACT,IAAI,CAAC,iBAAiB,CAAC,YAAY,GAAGA;aAEtC,IAAI,CAAC,cAAc,CAACA,SAAS;IAEjC;AAs5CF;AAEA,eAAeD"}
@@ -340,10 +340,13 @@ class PlaygroundServer {
340
340
  scrcpyPort: this.scrcpyPort
341
341
  });
342
342
  }
343
+ isEffectivelyConnected() {
344
+ const rawConnected = this.sessionManager ? Boolean(this._activeConnection.session?.connected && this._activeConnection.agent) : Boolean(this._activeConnection.agent);
345
+ return rawConnected || !this._agentReady;
346
+ }
343
347
  getSessionInfo() {
344
- const connected = this.sessionManager ? Boolean(this._activeConnection.session?.connected && this._activeConnection.agent) : Boolean(this._activeConnection.agent);
345
348
  return {
346
- connected,
349
+ connected: this.isEffectivelyConnected(),
347
350
  displayName: this._activeConnection.session?.displayName,
348
351
  metadata: {
349
352
  ...this._activeConnection.session?.metadata || {}
@@ -353,11 +356,10 @@ class PlaygroundServer {
353
356
  };
354
357
  }
355
358
  buildSessionMetadata() {
356
- const sessionConnected = this.sessionManager ? Boolean(this._activeConnection.session?.connected && this._activeConnection.agent) : Boolean(this._activeConnection.agent);
357
359
  return {
358
360
  ...this._basePreparedMetadata || {},
359
361
  ...this._activeConnection.session?.metadata || {},
360
- sessionConnected,
362
+ sessionConnected: this.isEffectivelyConnected(),
361
363
  sessionDisplayName: this._activeConnection.session?.displayName,
362
364
  setupState: this.sessionSetupState,
363
365
  ...this.sessionSetupBlockingReason ? {