@midscene/playground 1.9.6 → 1.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/es/adapters/local-execution.mjs +3 -3
  2. package/dist/es/adapters/local-execution.mjs.map +1 -1
  3. package/dist/es/adapters/remote-execution.mjs +35 -0
  4. package/dist/es/adapters/remote-execution.mjs.map +1 -1
  5. package/dist/es/common.mjs +30 -3
  6. package/dist/es/common.mjs.map +1 -1
  7. package/dist/es/index.browser.mjs.map +1 -1
  8. package/dist/es/mjpeg-hub.mjs +3 -0
  9. package/dist/es/mjpeg-hub.mjs.map +1 -1
  10. package/dist/es/mjpeg-stream-handler.mjs +6 -0
  11. package/dist/es/mjpeg-stream-handler.mjs.map +1 -1
  12. package/dist/es/platform.mjs.map +1 -1
  13. package/dist/es/sdk/index.mjs +7 -0
  14. package/dist/es/sdk/index.mjs.map +1 -1
  15. package/dist/es/server.mjs +563 -42
  16. package/dist/es/server.mjs.map +1 -1
  17. package/dist/lib/adapters/local-execution.js +3 -3
  18. package/dist/lib/adapters/local-execution.js.map +1 -1
  19. package/dist/lib/adapters/remote-execution.js +35 -0
  20. package/dist/lib/adapters/remote-execution.js.map +1 -1
  21. package/dist/lib/common.js +30 -3
  22. package/dist/lib/common.js.map +1 -1
  23. package/dist/lib/index.browser.js.map +1 -1
  24. package/dist/lib/mjpeg-hub.js +3 -0
  25. package/dist/lib/mjpeg-hub.js.map +1 -1
  26. package/dist/lib/mjpeg-stream-handler.js +6 -0
  27. package/dist/lib/mjpeg-stream-handler.js.map +1 -1
  28. package/dist/lib/platform.js.map +1 -1
  29. package/dist/lib/sdk/index.js +7 -0
  30. package/dist/lib/sdk/index.js.map +1 -1
  31. package/dist/lib/server.js +560 -39
  32. package/dist/lib/server.js.map +1 -1
  33. package/dist/types/adapters/local-execution.d.ts +3 -2
  34. package/dist/types/adapters/remote-execution.d.ts +2 -1
  35. package/dist/types/index.browser.d.ts +1 -1
  36. package/dist/types/index.d.ts +1 -1
  37. package/dist/types/mjpeg-hub.d.ts +1 -0
  38. package/dist/types/mjpeg-stream-handler.d.ts +2 -0
  39. package/dist/types/platform.d.ts +104 -0
  40. package/dist/types/sdk/index.d.ts +3 -2
  41. package/dist/types/server.d.ts +9 -0
  42. package/dist/types/types.d.ts +5 -0
  43. package/package.json +3 -3
  44. package/static/index.html +1 -1
  45. package/static/static/css/{index.ab28104a.css → index.1293237f.css} +2 -2
  46. package/static/static/css/{index.ab28104a.css.map → index.1293237f.css.map} +1 -1
  47. package/static/static/js/{596.5426be9e.js → 905.8d12588e.js} +17 -17
  48. package/static/static/js/905.8d12588e.js.map +1 -0
  49. package/static/static/js/index.50e06ed5.js +948 -0
  50. package/static/static/js/index.50e06ed5.js.map +1 -0
  51. package/static/static/js/596.5426be9e.js.map +0 -1
  52. package/static/static/js/index.134d5099.js +0 -940
  53. package/static/static/js/index.134d5099.js.map +0 -1
  54. /package/static/static/js/{596.5426be9e.js.LICENSE.txt → 905.8d12588e.js.LICENSE.txt} +0 -0
  55. /package/static/static/js/{index.134d5099.js.LICENSE.txt → index.50e06ed5.js.LICENSE.txt} +0 -0
@@ -122,7 +122,7 @@ class LocalExecutionAdapter extends BasePlaygroundAdapter {
122
122
  const dumpString = agent.dumpDataString();
123
123
  if (dumpString) {
124
124
  const groupedDump = ReportActionDump.fromSerializedString(dumpString);
125
- response.dump = groupedDump.executions?.[0] || null;
125
+ response.dump = groupedDump;
126
126
  }
127
127
  }
128
128
  } catch (error) {
@@ -161,7 +161,7 @@ class LocalExecutionAdapter extends BasePlaygroundAdapter {
161
161
  const dumpString = this.agent.dumpDataString();
162
162
  if (dumpString) {
163
163
  const groupedDump = ReportActionDump.fromSerializedString(dumpString);
164
- dump = groupedDump.executions?.[0] ?? null;
164
+ dump = groupedDump;
165
165
  }
166
166
  }
167
167
  } catch (error) {
@@ -203,7 +203,7 @@ class LocalExecutionAdapter extends BasePlaygroundAdapter {
203
203
  const dumpString = this.agent.dumpDataString();
204
204
  if (dumpString) {
205
205
  const groupedDump = ReportActionDump.fromSerializedString(dumpString);
206
- response.dump = groupedDump.executions?.[0] || null;
206
+ response.dump = groupedDump;
207
207
  }
208
208
  }
209
209
  if (this.agent?.reportHTMLString) response.reportHTML = this.agent.reportHTMLString() || null;
@@ -1 +1 @@
1
- {"version":3,"file":"adapters/local-execution.mjs","sources":["../../../src/adapters/local-execution.ts"],"sourcesContent":["import type {\n ConnectivityTestResult,\n DeviceAction,\n ExecutionDump,\n} from '@midscene/core';\nimport { ReportActionDump, runConnectivityTest } from '@midscene/core';\nimport {\n globalModelConfigManager,\n overrideAIConfig,\n} from '@midscene/shared/env';\nimport { uuid } from '@midscene/shared/utils';\nimport { executeAction, parseStructuredParams } from '../common';\nimport {\n type PlaygroundRuntimeInfo,\n buildRuntimeInfo,\n} from '../runtime-metadata';\nimport type {\n AgentFactory,\n ExecutionOptions,\n FormValue,\n PlaygroundAgent,\n} from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class LocalExecutionAdapter extends BasePlaygroundAdapter {\n private agent: PlaygroundAgent | null;\n private agentFactory?: AgentFactory; // Factory function for recreating agent\n private dumpUpdateCallback?: (\n dump: string,\n executionDump?: ExecutionDump,\n ) => void;\n private progressCallback?: (tip: string) => void;\n private readonly _id: string; // Unique identifier for this local adapter instance\n private currentRequestId?: string; // Track current request to prevent stale callbacks\n\n constructor(agent?: PlaygroundAgent, agentFactory?: AgentFactory) {\n super();\n this.agent = agent ?? null;\n this.agentFactory = agentFactory;\n this._id = uuid(); // Generate unique ID for local adapter\n }\n\n // Get adapter ID\n get id(): string {\n return this._id;\n }\n\n onDumpUpdate(\n callback: (dump: string, executionDump?: ExecutionDump) => void,\n ): void {\n // Clear any existing callback before setting new one\n this.dumpUpdateCallback = undefined;\n // Set the new callback\n this.dumpUpdateCallback = callback;\n }\n\n // Set progress callback for monitoring operation status\n setProgressCallback(callback: (tip: string) => void): void {\n this.progressCallback = undefined;\n this.progressCallback = callback;\n }\n\n async parseStructuredParams(\n action: DeviceAction<unknown>,\n params: Record<string, unknown>,\n options: ExecutionOptions,\n ): Promise<unknown[]> {\n // Use shared implementation from common.ts\n return await parseStructuredParams(action, params, options);\n }\n\n formatErrorMessage(error: any): string {\n const errorMessage = error?.message || '';\n if (errorMessage.includes('of different extension')) {\n return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';\n }\n return this.formatBasicErrorMessage(error);\n }\n\n // Local execution - use base implementation\n // (inherits default executeAction from BasePlaygroundAdapter)\n\n // Local execution gets actionSpace from internal agent (parameter is for backward compatibility)\n async getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]> {\n // If agent doesn't exist but we have a factory, create one temporarily to get actionSpace\n if (!this.agent && this.agentFactory) {\n try {\n this.agent = await this.agentFactory();\n } catch (error) {\n console.warn('Failed to create agent for actionSpace:', error);\n return [];\n }\n }\n\n // Priority 1: Use agent's getActionSpace method\n if (this.agent?.getActionSpace) {\n return await this.agent.getActionSpace();\n }\n\n // Priority 2: Use agent's interface.actionSpace method\n if (\n this.agent &&\n 'interface' in this.agent &&\n typeof this.agent.interface === 'object'\n ) {\n const page = this.agent.interface as {\n actionSpace?: () => DeviceAction<unknown>[];\n };\n if (page?.actionSpace) {\n return page.actionSpace();\n }\n }\n\n // Priority 3: Fallback to context parameter (for backward compatibility with tests)\n if (context && typeof context === 'object' && 'actionSpace' in context) {\n const contextPage = context as {\n actionSpace: () => DeviceAction<unknown>[];\n };\n return contextPage.actionSpace();\n }\n\n return [];\n }\n\n // Local execution doesn't use a server, so always return true\n async checkStatus(): Promise<boolean> {\n return true;\n }\n\n async overrideConfig(aiConfig: Record<string, unknown>): Promise<void> {\n // For local execution, use the shared env override function\n overrideAIConfig(aiConfig);\n console.log('Config updated. Agent will be recreated on next execution.');\n }\n\n async runConnectivityTest(): Promise<ConnectivityTestResult> {\n return runConnectivityTest({\n defaultModelConfig: globalModelConfigManager.getModelConfig('default'),\n planningModelConfig: globalModelConfigManager.getModelConfig('planning'),\n insightModelConfig: globalModelConfigManager.getModelConfig('insight'),\n });\n }\n\n /**\n * Safely detaches the Chrome debugger without destroying the agent.\n * This removes the \"Debugger attached\" banner from the browser window\n * while keeping the agent instance intact for potential reuse.\n * Called on errors to improve user experience by cleaning up the UI.\n */\n private async detachDebuggerSafely() {\n try {\n const page = this.agent?.interface as\n | { detachDebugger?: () => Promise<void> }\n | undefined;\n await page?.detachDebugger?.();\n } catch (error) {\n console.warn('Failed to detach debugger:', error);\n }\n }\n\n async executeAction(\n actionType: string,\n value: FormValue,\n options: ExecutionOptions,\n ): Promise<unknown> {\n // If agentFactory is provided, always recreate agent with latest config before execution\n if (this.agentFactory) {\n if (this.agent) {\n console.log('Destroying old agent before execution...');\n try {\n await this.agent.destroy?.();\n } catch (error) {\n console.warn('Failed to destroy old agent:', error);\n }\n this.agent = null;\n }\n\n // Create new agent with latest config\n await this.recreateAgent();\n }\n\n // Agent must exist (either recreated or provided in constructor)\n if (!this.agent) {\n throw new Error(\n 'No agent available. Please provide either an agent instance or agentFactory.',\n );\n }\n\n const agent = this.agent;\n\n // Get actionSpace using our simplified getActionSpace method\n const actionSpace = await this.getActionSpace();\n let removeListener: (() => void) | undefined;\n\n // Reset dump at the start of execution to ensure clean state\n try {\n agent.resetDump?.();\n } catch (error: unknown) {\n console.warn('Failed to reset dump before execution:', error);\n }\n\n // Setup dump update tracking if requestId is provided\n if (options.requestId) {\n // Track current request ID to prevent stale callbacks\n this.currentRequestId = options.requestId;\n\n // Add listener and save remove function\n removeListener = agent.addDumpUpdateListener(\n (dump: string, executionDump?: ExecutionDump) => {\n // Only process if this is still the current request\n if (this.currentRequestId !== options.requestId) {\n return;\n }\n\n // Forward to external callback\n if (this.dumpUpdateCallback) {\n this.dumpUpdateCallback(dump, executionDump);\n }\n },\n );\n }\n\n try {\n let result = null;\n let executionError = null;\n\n try {\n // Call the base implementation with the original signature\n result = await executeAction(\n agent,\n actionType,\n actionSpace,\n value,\n options,\n );\n } catch (error: unknown) {\n // Capture error but don't throw yet - we need to get dump/reportHTML first\n executionError = error;\n }\n\n // Always construct response with dump and reportHTML, regardless of success/failure\n const response = {\n result,\n dump: null as unknown,\n reportHTML: null as string | null,\n error: executionError\n ? executionError instanceof Error\n ? executionError.message\n : String(executionError)\n : null,\n };\n\n // Get dump data - separate try-catch to ensure dump is retrieved even if reportHTML fails\n try {\n if (agent.dumpDataString) {\n const dumpString = agent.dumpDataString();\n if (dumpString) {\n const groupedDump =\n ReportActionDump.fromSerializedString(dumpString);\n response.dump = groupedDump.executions?.[0] || null;\n }\n }\n } catch (error: unknown) {\n console.warn('Failed to get dump from agent:', error);\n }\n\n // Try to get reportHTML - may fail in browser environment (fs not available)\n try {\n if (agent.reportHTMLString) {\n response.reportHTML = agent.reportHTMLString() || null;\n }\n } catch (error: unknown) {\n // reportHTMLString may throw in browser environment\n // This is expected in chrome-extension, continue without reportHTML\n }\n\n // Write out action dumps - may also fail in browser environment\n try {\n if (agent.writeOutActionDumps) {\n agent.writeOutActionDumps();\n }\n } catch (error: unknown) {\n // writeOutActionDumps may fail in browser environment\n }\n\n // Don't throw the error - return it in response so caller can access dump/reportHTML\n // The caller (usePlaygroundExecution) will check response.error to determine success\n return response;\n } finally {\n // Remove listener to prevent accumulation\n if (removeListener) {\n removeListener();\n }\n }\n }\n\n /**\n * Recreate agent instance using the factory function.\n * Called automatically when executeAction is called.\n */\n private async recreateAgent(): Promise<void> {\n if (!this.agentFactory) {\n throw new Error(\n 'Cannot recreate agent: factory function not provided. Please provide agentFactory in PlaygroundConfig to enable agent recreation.',\n );\n }\n\n console.log('Creating new agent with latest config...');\n try {\n this.agent = await this.agentFactory();\n console.log('Agent created successfully');\n } catch (error) {\n console.error('Failed to create agent:', error);\n throw error;\n }\n }\n\n // Local execution task cancellation - returns dump and reportHTML before destroying\n async cancelTask(_requestId: string): Promise<{\n error?: string;\n success?: boolean;\n dump?: ExecutionDump | null;\n reportHTML?: string | null;\n }> {\n if (!this.agent) {\n return { error: 'No active agent found for this requestId' };\n }\n\n // Get execution data BEFORE destroying the agent\n let dump: ExecutionDump | null = null;\n let reportHTML: string | null = null;\n\n // Get dump data separately - don't let reportHTML errors affect dump retrieval\n // IMPORTANT: Must extract dump BEFORE agent.destroy(), as dump is stored in agent memory\n try {\n if (typeof this.agent.dumpDataString === 'function') {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n // dumpDataString() returns ReportActionDump: { executions: ExecutionDump[] }\n // In Playground, each \"Run\" creates one execution, so we take executions[0]\n const groupedDump = ReportActionDump.fromSerializedString(dumpString);\n dump = groupedDump.executions?.[0] ?? null;\n }\n }\n } catch (error) {\n console.warn(\n '[LocalExecutionAdapter] Failed to get dump data before cancel:',\n error,\n );\n }\n\n // Try to get reportHTML separately - this may fail in browser environment\n // where fs.readFileSync is not available\n try {\n if (typeof this.agent.reportHTMLString === 'function') {\n const html = this.agent.reportHTMLString();\n if (\n html &&\n typeof html === 'string' &&\n !html.includes('REPLACE_ME_WITH_REPORT_HTML')\n ) {\n reportHTML = html;\n }\n }\n } catch (error) {\n // reportHTMLString may throw in browser environment (fs not available)\n // This is expected, just continue with dump data only\n console.warn(\n '[LocalExecutionAdapter] reportHTMLString not available in this environment',\n );\n }\n\n try {\n await this.agent.destroy?.();\n this.agent = null; // Clear agent reference\n return { success: true, dump, reportHTML };\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(\n `[LocalExecutionAdapter] Failed to cancel agent: ${errorMessage}`,\n );\n return { error: `Failed to cancel: ${errorMessage}`, dump, reportHTML };\n }\n }\n\n /**\n * Get current execution data without resetting\n * This allows retrieving dump and report when execution is stopped\n */\n async getCurrentExecutionData(): Promise<{\n dump: ExecutionDump | null;\n reportHTML: string | null;\n }> {\n const response = {\n dump: null as ExecutionDump | null,\n reportHTML: null as string | null,\n };\n\n try {\n // Get dump data\n if (this.agent?.dumpDataString) {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n const groupedDump = ReportActionDump.fromSerializedString(dumpString);\n response.dump = groupedDump.executions?.[0] || null;\n }\n }\n\n // Get report HTML\n if (this.agent?.reportHTMLString) {\n response.reportHTML = this.agent.reportHTMLString() || null;\n }\n } catch (error: unknown) {\n console.error('Failed to get current execution data:', error);\n }\n\n return response;\n }\n\n // Get interface information from the agent\n async getInterfaceInfo(): Promise<{\n type: string;\n description?: string;\n size?: { width: number; height: number };\n actionTypes?: string[];\n } | null> {\n if (!this.agent?.interface) {\n return null;\n }\n\n try {\n const type = this.agent.interface.interfaceType || 'Unknown';\n const description = this.agent.interface.describe?.() || undefined;\n const size =\n typeof this.agent.interface.size === 'function'\n ? await this.agent.interface.size()\n : undefined;\n const actionTypes =\n typeof this.agent.interface.actionSpace === 'function'\n ? this.agent.interface\n .actionSpace()\n .map((action) => action?.name)\n .filter((name): name is string => typeof name === 'string')\n : undefined;\n\n return {\n type,\n description,\n ...(size ? { size } : {}),\n ...(actionTypes ? { actionTypes } : {}),\n };\n } catch (error: unknown) {\n console.error('Failed to get interface info:', error);\n return null;\n }\n }\n\n async getRuntimeInfo(): Promise<PlaygroundRuntimeInfo | null> {\n if (!this.agent?.interface) {\n return null;\n }\n\n try {\n return buildRuntimeInfo({\n interfaceType: this.agent.interface.interfaceType || 'Unknown',\n interfaceDescription: this.agent.interface.describe?.() || undefined,\n supportsScreenshot:\n typeof this.agent.interface.screenshotBase64 === 'function',\n mjpegStreamUrl: this.agent.interface.mjpegStreamUrl,\n });\n } catch (error: unknown) {\n console.error('Failed to get runtime info:', error);\n return null;\n }\n }\n}\n"],"names":["LocalExecutionAdapter","BasePlaygroundAdapter","callback","undefined","action","params","options","parseStructuredParams","error","errorMessage","context","console","page","contextPage","aiConfig","overrideAIConfig","runConnectivityTest","globalModelConfigManager","actionType","value","Error","agent","actionSpace","removeListener","dump","executionDump","result","executionError","executeAction","response","String","dumpString","groupedDump","ReportActionDump","_requestId","reportHTML","html","type","description","size","actionTypes","name","buildRuntimeInfo","agentFactory","uuid"],"mappings":"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"}
1
+ {"version":3,"file":"adapters/local-execution.mjs","sources":["../../../src/adapters/local-execution.ts"],"sourcesContent":["import type {\n ConnectivityTestResult,\n DeviceAction,\n ExecutionDump,\n} from '@midscene/core';\nimport { ReportActionDump, runConnectivityTest } from '@midscene/core';\nimport {\n globalModelConfigManager,\n overrideAIConfig,\n} from '@midscene/shared/env';\nimport { uuid } from '@midscene/shared/utils';\nimport { executeAction, parseStructuredParams } from '../common';\nimport {\n type PlaygroundRuntimeInfo,\n buildRuntimeInfo,\n} from '../runtime-metadata';\nimport type {\n AgentFactory,\n ExecutionOptions,\n FormValue,\n PlaygroundAgent,\n} from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class LocalExecutionAdapter extends BasePlaygroundAdapter {\n private agent: PlaygroundAgent | null;\n private agentFactory?: AgentFactory; // Factory function for recreating agent\n private dumpUpdateCallback?: (\n dump: string,\n executionDump?: ExecutionDump,\n ) => void;\n private progressCallback?: (tip: string) => void;\n private readonly _id: string; // Unique identifier for this local adapter instance\n private currentRequestId?: string; // Track current request to prevent stale callbacks\n\n constructor(agent?: PlaygroundAgent, agentFactory?: AgentFactory) {\n super();\n this.agent = agent ?? null;\n this.agentFactory = agentFactory;\n this._id = uuid(); // Generate unique ID for local adapter\n }\n\n // Get adapter ID\n get id(): string {\n return this._id;\n }\n\n onDumpUpdate(\n callback: (dump: string, executionDump?: ExecutionDump) => void,\n ): void {\n // Clear any existing callback before setting new one\n this.dumpUpdateCallback = undefined;\n // Set the new callback\n this.dumpUpdateCallback = callback;\n }\n\n // Set progress callback for monitoring operation status\n setProgressCallback(callback: (tip: string) => void): void {\n this.progressCallback = undefined;\n this.progressCallback = callback;\n }\n\n async parseStructuredParams(\n action: DeviceAction<unknown>,\n params: Record<string, unknown>,\n options: ExecutionOptions,\n ): Promise<unknown[]> {\n // Use shared implementation from common.ts\n return await parseStructuredParams(action, params, options);\n }\n\n formatErrorMessage(error: any): string {\n const errorMessage = error?.message || '';\n if (errorMessage.includes('of different extension')) {\n return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';\n }\n return this.formatBasicErrorMessage(error);\n }\n\n // Local execution - use base implementation\n // (inherits default executeAction from BasePlaygroundAdapter)\n\n // Local execution gets actionSpace from internal agent (parameter is for backward compatibility)\n async getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]> {\n // If agent doesn't exist but we have a factory, create one temporarily to get actionSpace\n if (!this.agent && this.agentFactory) {\n try {\n this.agent = await this.agentFactory();\n } catch (error) {\n console.warn('Failed to create agent for actionSpace:', error);\n return [];\n }\n }\n\n // Priority 1: Use agent's getActionSpace method\n if (this.agent?.getActionSpace) {\n return await this.agent.getActionSpace();\n }\n\n // Priority 2: Use agent's interface.actionSpace method\n if (\n this.agent &&\n 'interface' in this.agent &&\n typeof this.agent.interface === 'object'\n ) {\n const page = this.agent.interface as {\n actionSpace?: () => DeviceAction<unknown>[];\n };\n if (page?.actionSpace) {\n return page.actionSpace();\n }\n }\n\n // Priority 3: Fallback to context parameter (for backward compatibility with tests)\n if (context && typeof context === 'object' && 'actionSpace' in context) {\n const contextPage = context as {\n actionSpace: () => DeviceAction<unknown>[];\n };\n return contextPage.actionSpace();\n }\n\n return [];\n }\n\n // Local execution doesn't use a server, so always return true\n async checkStatus(): Promise<boolean> {\n return true;\n }\n\n async overrideConfig(aiConfig: Record<string, unknown>): Promise<void> {\n // For local execution, use the shared env override function\n overrideAIConfig(aiConfig);\n console.log('Config updated. Agent will be recreated on next execution.');\n }\n\n async runConnectivityTest(): Promise<ConnectivityTestResult> {\n return runConnectivityTest({\n defaultModelConfig: globalModelConfigManager.getModelConfig('default'),\n planningModelConfig: globalModelConfigManager.getModelConfig('planning'),\n insightModelConfig: globalModelConfigManager.getModelConfig('insight'),\n });\n }\n\n /**\n * Safely detaches the Chrome debugger without destroying the agent.\n * This removes the \"Debugger attached\" banner from the browser window\n * while keeping the agent instance intact for potential reuse.\n * Called on errors to improve user experience by cleaning up the UI.\n */\n private async detachDebuggerSafely() {\n try {\n const page = this.agent?.interface as\n | { detachDebugger?: () => Promise<void> }\n | undefined;\n await page?.detachDebugger?.();\n } catch (error) {\n console.warn('Failed to detach debugger:', error);\n }\n }\n\n async executeAction(\n actionType: string,\n value: FormValue,\n options: ExecutionOptions,\n ): Promise<unknown> {\n // If agentFactory is provided, always recreate agent with latest config before execution\n if (this.agentFactory) {\n if (this.agent) {\n console.log('Destroying old agent before execution...');\n try {\n await this.agent.destroy?.();\n } catch (error) {\n console.warn('Failed to destroy old agent:', error);\n }\n this.agent = null;\n }\n\n // Create new agent with latest config\n await this.recreateAgent();\n }\n\n // Agent must exist (either recreated or provided in constructor)\n if (!this.agent) {\n throw new Error(\n 'No agent available. Please provide either an agent instance or agentFactory.',\n );\n }\n\n const agent = this.agent;\n\n // Get actionSpace using our simplified getActionSpace method\n const actionSpace = await this.getActionSpace();\n let removeListener: (() => void) | undefined;\n\n // Reset dump at the start of execution to ensure clean state\n try {\n agent.resetDump?.();\n } catch (error: unknown) {\n console.warn('Failed to reset dump before execution:', error);\n }\n\n // Setup dump update tracking if requestId is provided\n if (options.requestId) {\n // Track current request ID to prevent stale callbacks\n this.currentRequestId = options.requestId;\n\n // Add listener and save remove function\n removeListener = agent.addDumpUpdateListener(\n (dump: string, executionDump?: ExecutionDump) => {\n // Only process if this is still the current request\n if (this.currentRequestId !== options.requestId) {\n return;\n }\n\n // Forward to external callback\n if (this.dumpUpdateCallback) {\n this.dumpUpdateCallback(dump, executionDump);\n }\n },\n );\n }\n\n try {\n let result = null;\n let executionError = null;\n\n try {\n // Call the base implementation with the original signature\n result = await executeAction(\n agent,\n actionType,\n actionSpace,\n value,\n options,\n );\n } catch (error: unknown) {\n // Capture error but don't throw yet - we need to get dump/reportHTML first\n executionError = error;\n }\n\n // Always construct response with dump and reportHTML, regardless of success/failure\n const response = {\n result,\n dump: null as unknown,\n reportHTML: null as string | null,\n error: executionError\n ? executionError instanceof Error\n ? executionError.message\n : String(executionError)\n : null,\n };\n\n // Get dump data - separate try-catch to ensure dump is retrieved even if reportHTML fails\n try {\n if (agent.dumpDataString) {\n const dumpString = agent.dumpDataString();\n if (dumpString) {\n const groupedDump =\n ReportActionDump.fromSerializedString(dumpString);\n response.dump = groupedDump;\n }\n }\n } catch (error: unknown) {\n console.warn('Failed to get dump from agent:', error);\n }\n\n // Try to get reportHTML - may fail in browser environment (fs not available)\n try {\n if (agent.reportHTMLString) {\n response.reportHTML = agent.reportHTMLString() || null;\n }\n } catch (error: unknown) {\n // reportHTMLString may throw in browser environment\n // This is expected in chrome-extension, continue without reportHTML\n }\n\n // Write out action dumps - may also fail in browser environment\n try {\n if (agent.writeOutActionDumps) {\n agent.writeOutActionDumps();\n }\n } catch (error: unknown) {\n // writeOutActionDumps may fail in browser environment\n }\n\n // Don't throw the error - return it in response so caller can access dump/reportHTML\n // The caller (usePlaygroundExecution) will check response.error to determine success\n return response;\n } finally {\n // Remove listener to prevent accumulation\n if (removeListener) {\n removeListener();\n }\n }\n }\n\n /**\n * Recreate agent instance using the factory function.\n * Called automatically when executeAction is called.\n */\n private async recreateAgent(): Promise<void> {\n if (!this.agentFactory) {\n throw new Error(\n 'Cannot recreate agent: factory function not provided. Please provide agentFactory in PlaygroundConfig to enable agent recreation.',\n );\n }\n\n console.log('Creating new agent with latest config...');\n try {\n this.agent = await this.agentFactory();\n console.log('Agent created successfully');\n } catch (error) {\n console.error('Failed to create agent:', error);\n throw error;\n }\n }\n\n // Local execution task cancellation - returns dump and reportHTML before destroying\n async cancelTask(_requestId: string): Promise<{\n error?: string;\n success?: boolean;\n dump?: ExecutionDump | ReportActionDump | null;\n reportHTML?: string | null;\n }> {\n if (!this.agent) {\n return { error: 'No active agent found for this requestId' };\n }\n\n // Get execution data BEFORE destroying the agent\n let dump: ExecutionDump | ReportActionDump | null = null;\n let reportHTML: string | null = null;\n\n // Get dump data separately - don't let reportHTML errors affect dump retrieval\n // IMPORTANT: Must extract dump BEFORE agent.destroy(), as dump is stored in agent memory\n try {\n if (typeof this.agent.dumpDataString === 'function') {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n const groupedDump = ReportActionDump.fromSerializedString(dumpString);\n dump = groupedDump;\n }\n }\n } catch (error) {\n console.warn(\n '[LocalExecutionAdapter] Failed to get dump data before cancel:',\n error,\n );\n }\n\n // Try to get reportHTML separately - this may fail in browser environment\n // where fs.readFileSync is not available\n try {\n if (typeof this.agent.reportHTMLString === 'function') {\n const html = this.agent.reportHTMLString();\n if (\n html &&\n typeof html === 'string' &&\n !html.includes('REPLACE_ME_WITH_REPORT_HTML')\n ) {\n reportHTML = html;\n }\n }\n } catch (error) {\n // reportHTMLString may throw in browser environment (fs not available)\n // This is expected, just continue with dump data only\n console.warn(\n '[LocalExecutionAdapter] reportHTMLString not available in this environment',\n );\n }\n\n try {\n await this.agent.destroy?.();\n this.agent = null; // Clear agent reference\n return { success: true, dump, reportHTML };\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(\n `[LocalExecutionAdapter] Failed to cancel agent: ${errorMessage}`,\n );\n return { error: `Failed to cancel: ${errorMessage}`, dump, reportHTML };\n }\n }\n\n /**\n * Get current execution data without resetting\n * This allows retrieving dump and report when execution is stopped\n */\n async getCurrentExecutionData(): Promise<{\n dump: ExecutionDump | ReportActionDump | null;\n reportHTML: string | null;\n }> {\n const response = {\n dump: null as ExecutionDump | ReportActionDump | null,\n reportHTML: null as string | null,\n };\n\n try {\n // Get dump data\n if (this.agent?.dumpDataString) {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n const groupedDump = ReportActionDump.fromSerializedString(dumpString);\n response.dump = groupedDump;\n }\n }\n\n // Get report HTML\n if (this.agent?.reportHTMLString) {\n response.reportHTML = this.agent.reportHTMLString() || null;\n }\n } catch (error: unknown) {\n console.error('Failed to get current execution data:', error);\n }\n\n return response;\n }\n\n // Get interface information from the agent\n async getInterfaceInfo(): Promise<{\n type: string;\n description?: string;\n size?: { width: number; height: number };\n actionTypes?: string[];\n } | null> {\n if (!this.agent?.interface) {\n return null;\n }\n\n try {\n const type = this.agent.interface.interfaceType || 'Unknown';\n const description = this.agent.interface.describe?.() || undefined;\n const size =\n typeof this.agent.interface.size === 'function'\n ? await this.agent.interface.size()\n : undefined;\n const actionTypes =\n typeof this.agent.interface.actionSpace === 'function'\n ? this.agent.interface\n .actionSpace()\n .map((action) => action?.name)\n .filter((name): name is string => typeof name === 'string')\n : undefined;\n\n return {\n type,\n description,\n ...(size ? { size } : {}),\n ...(actionTypes ? { actionTypes } : {}),\n };\n } catch (error: unknown) {\n console.error('Failed to get interface info:', error);\n return null;\n }\n }\n\n async getRuntimeInfo(): Promise<PlaygroundRuntimeInfo | null> {\n if (!this.agent?.interface) {\n return null;\n }\n\n try {\n return buildRuntimeInfo({\n interfaceType: this.agent.interface.interfaceType || 'Unknown',\n interfaceDescription: this.agent.interface.describe?.() || undefined,\n supportsScreenshot:\n typeof this.agent.interface.screenshotBase64 === 'function',\n mjpegStreamUrl: this.agent.interface.mjpegStreamUrl,\n });\n } catch (error: unknown) {\n console.error('Failed to get runtime info:', error);\n return null;\n }\n }\n}\n"],"names":["LocalExecutionAdapter","BasePlaygroundAdapter","callback","undefined","action","params","options","parseStructuredParams","error","errorMessage","context","console","page","contextPage","aiConfig","overrideAIConfig","runConnectivityTest","globalModelConfigManager","actionType","value","Error","agent","actionSpace","removeListener","dump","executionDump","result","executionError","executeAction","response","String","dumpString","groupedDump","ReportActionDump","_requestId","reportHTML","html","type","description","size","actionTypes","name","buildRuntimeInfo","agentFactory","uuid"],"mappings":"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"}
@@ -128,6 +128,10 @@ class RemoteExecutionAdapter extends BasePlaygroundAdapter {
128
128
  key: 'deviceOptions',
129
129
  value: options.deviceOptions
130
130
  },
131
+ {
132
+ key: 'reportDisplay',
133
+ value: options.reportDisplay
134
+ },
131
135
  {
132
136
  key: 'params',
133
137
  value: value.params
@@ -436,6 +440,37 @@ class RemoteExecutionAdapter extends BasePlaygroundAdapter {
436
440
  };
437
441
  }
438
442
  }
443
+ async describeRecorderEventAtPoint(event) {
444
+ if (!this.serverUrl) return {
445
+ ok: false,
446
+ error: 'No server URL configured'
447
+ };
448
+ try {
449
+ const response = await fetch(`${this.serverUrl}/recorder/describe-event`, {
450
+ method: 'POST',
451
+ headers: {
452
+ 'Content-Type': 'application/json'
453
+ },
454
+ body: JSON.stringify({
455
+ event
456
+ })
457
+ });
458
+ const data = await response.json().catch(()=>null);
459
+ if (!response.ok) return {
460
+ ok: false,
461
+ error: data?.error || `Recorder describe request failed (${response.status})`
462
+ };
463
+ return data || {
464
+ ok: false,
465
+ error: 'Empty recorder describe response'
466
+ };
467
+ } catch (error) {
468
+ return {
469
+ ok: false,
470
+ error: error instanceof Error ? error.message : 'Failed to describe recorder event'
471
+ };
472
+ }
473
+ }
439
474
  async getInterfaceInfo() {
440
475
  if (!this.serverUrl) return null;
441
476
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"adapters/remote-execution.mjs","sources":["../../../src/adapters/remote-execution.ts"],"sourcesContent":["import type {\n ConnectivityTestResult,\n DeviceAction,\n ExecutionDump,\n} from '@midscene/core';\nimport { parseStructuredParams } from '../common';\nimport type {\n PlaygroundRecorderCapabilitiesResult,\n PlaygroundRecorderEventsResult,\n PlaygroundRecorderSourceKind,\n PlaygroundRecorderStartResult,\n PlaygroundSessionSetup,\n PlaygroundSessionState,\n PlaygroundSessionTarget,\n} from '../platform';\nimport type { PlaygroundRuntimeInfo } from '../runtime-metadata';\nimport type { ExecutionOptions, FormValue, ValidationResult } from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class RemoteExecutionAdapter extends BasePlaygroundAdapter {\n private serverUrl?: string;\n private _id?: string;\n private dumpUpdateCallback?: (\n dump: string,\n executionDump?: ExecutionDump,\n ) => void;\n private pollingIntervalId?: ReturnType<typeof setInterval>;\n\n constructor(serverUrl: string) {\n super();\n this.serverUrl = serverUrl;\n }\n\n // Set dump update callback\n onDumpUpdate(\n callback: (dump: string, executionDump?: ExecutionDump) => void,\n ): void {\n this.dumpUpdateCallback = undefined;\n this.dumpUpdateCallback = callback;\n }\n\n // Get adapter ID (cached after first status check for remote)\n get id(): string | undefined {\n return this._id;\n }\n\n // Override validateParams for remote execution\n // Since schemas from server are JSON-serialized and lack .parse() method\n validateParams(\n value: FormValue,\n action: DeviceAction<unknown> | undefined,\n ): ValidationResult {\n if (!action?.paramSchema) {\n return { valid: true };\n }\n\n const needsStructuredParams = this.actionNeedsStructuredParams(action);\n\n if (!needsStructuredParams) {\n return { valid: true };\n }\n\n if (!value.params) {\n return { valid: false, errorMessage: 'Parameters are required' };\n }\n\n // For remote execution, perform basic validation without .parse()\n // Check if required fields are present\n if (action.paramSchema && typeof action.paramSchema === 'object') {\n const schema = action.paramSchema as any;\n if (schema.shape || schema.type === 'ZodObject') {\n const shape = schema.shape || {};\n const missingFields = Object.keys(shape).filter((key) => {\n const fieldDef = shape[key];\n // Check if field is required (not optional)\n const isOptional =\n fieldDef?.isOptional ||\n fieldDef?._def?.innerType || // ZodOptional\n fieldDef?._def?.typeName === 'ZodOptional';\n return (\n !isOptional &&\n (value.params![key] === undefined || value.params![key] === '')\n );\n });\n\n if (missingFields.length > 0) {\n return {\n valid: false,\n errorMessage: `Missing required parameters: ${missingFields.join(', ')}`,\n };\n }\n }\n }\n\n return { valid: true };\n }\n\n async parseStructuredParams(\n action: DeviceAction<unknown>,\n params: Record<string, unknown>,\n options: ExecutionOptions,\n ): Promise<unknown[]> {\n // Use shared implementation from common.ts\n return await parseStructuredParams(action, params, options);\n }\n\n formatErrorMessage(error: any): string {\n const message = error?.message || '';\n\n // Handle Android-specific errors\n const androidErrors = [\n {\n keyword: 'adb',\n message:\n 'ADB connection error. Please ensure device is connected and USB debugging is enabled.',\n },\n {\n keyword: 'UIAutomator',\n message:\n 'UIAutomator error. Please ensure the UIAutomator server is running on the device.',\n },\n ];\n\n const androidError = androidErrors.find(({ keyword }) =>\n message.includes(keyword),\n );\n if (androidError) {\n return androidError.message;\n }\n\n return this.formatBasicErrorMessage(error);\n }\n\n // Remote execution adapter - simplified interface\n async executeAction(\n actionType: string,\n value: FormValue,\n options: ExecutionOptions,\n ): Promise<unknown> {\n // If serverUrl is provided, use server-side execution\n if (this.serverUrl && typeof window !== 'undefined') {\n return this.executeViaServer(actionType, value, options);\n }\n\n throw new Error(\n 'Remote execution adapter requires server URL for execution',\n );\n }\n\n // Remote execution via server - uses same endpoint as requestPlaygroundServer\n private async executeViaServer(\n actionType: string,\n value: FormValue,\n options: ExecutionOptions,\n ): Promise<unknown> {\n const payload: Record<string, unknown> = {\n type: actionType,\n prompt: value.prompt,\n ...this.buildOptionalPayloadParams(options, value),\n };\n\n // Add context only if it exists (server can handle single agent case without context)\n if (options.context) {\n payload.context = options.context;\n }\n\n // Start polling if requestId is provided and dumpUpdateCallback is set\n if (options.requestId && this.dumpUpdateCallback) {\n this.startProgressPolling(options.requestId);\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/execute`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(\n `Server request failed (${response.status}): ${errorText}`,\n );\n }\n\n const result = await response.json();\n\n return result;\n } catch (error) {\n console.error('Execute via server failed:', error);\n throw error;\n } finally {\n // Stop polling when execution completes (success or error)\n this.stopProgressPolling();\n }\n }\n\n // Helper method to build optional payload parameters\n private buildOptionalPayloadParams(\n options: ExecutionOptions,\n value: FormValue,\n ): Record<string, unknown> {\n const optionalParams: Record<string, unknown> = {};\n\n // Add optional parameters only if they have meaningful values\n const optionalFields = [\n { key: 'requestId', value: options.requestId },\n { key: 'deepLocate', value: options.deepLocate },\n { key: 'deepThink', value: options.deepThink },\n { key: 'screenshotIncluded', value: options.screenshotIncluded },\n { key: 'domIncluded', value: options.domIncluded },\n { key: 'deviceOptions', value: options.deviceOptions },\n { key: 'params', value: value.params },\n ] as const;\n\n optionalFields.forEach(({ key, value }) => {\n if (value !== undefined && value !== null && value !== '') {\n optionalParams[key] = value;\n }\n });\n\n return optionalParams;\n }\n\n // Get action space from server with fallback\n async getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]> {\n // Try server first if available\n if (this.serverUrl && typeof window !== 'undefined') {\n try {\n const response = await fetch(`${this.serverUrl}/action-space`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ context }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get action space: ${response.statusText}`);\n }\n\n const result = await response.json();\n return Array.isArray(result) ? result : [];\n } catch (error) {\n console.error('Failed to get action space from server:', error);\n // Fall through to context fallback\n }\n }\n\n // Fallback: try context.actionSpace if available\n if (context && typeof context === 'object' && 'actionSpace' in context) {\n try {\n const actionSpaceMethod = (\n context as {\n actionSpace: () =>\n | DeviceAction<unknown>[]\n | Promise<DeviceAction<unknown>[]>;\n }\n ).actionSpace;\n const result = await actionSpaceMethod();\n return Array.isArray(result) ? result : [];\n } catch (error) {\n console.error('Failed to get action space from context:', error);\n }\n }\n\n return [];\n }\n\n // Uses base implementation for validateParams and createDisplayContent\n\n // Server communication methods\n async checkStatus(): Promise<boolean> {\n if (!this.serverUrl) {\n return false;\n }\n\n try {\n const res = await fetch(`${this.serverUrl}/status`);\n if (res.status === 200) {\n // Try to extract id from response\n try {\n const data = await res.json();\n if (data.id && typeof data.id === 'string') {\n this._id = data.id;\n }\n } catch (jsonError) {\n // If JSON parsing fails, id remains undefined but status is still OK\n console.debug('Failed to parse status response:', jsonError);\n }\n return true;\n }\n return false;\n } catch (error) {\n console.warn('Server status check failed:', error);\n return false;\n }\n }\n\n async overrideConfig(aiConfig: Record<string, unknown>): Promise<void> {\n if (!this.serverUrl) {\n throw new Error('Server URL not configured');\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/config`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ aiConfig }),\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n const detail = body?.error || response.statusText;\n throw new Error(detail);\n }\n } catch (error) {\n console.error('Failed to override server config:', error);\n throw error;\n }\n }\n\n async runConnectivityTest(): Promise<ConnectivityTestResult> {\n if (!this.serverUrl) {\n throw new Error('Server URL not configured');\n }\n\n const response = await fetch(`${this.serverUrl}/connectivity-test`, {\n method: 'POST',\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n const detail = body?.error || response.statusText;\n throw new Error(detail);\n }\n\n return response.json();\n }\n\n async getTaskProgress(requestId: string): Promise<{\n executionDump?: ExecutionDump;\n }> {\n if (!this.serverUrl) {\n return {};\n }\n\n if (!requestId?.trim()) {\n console.warn('Invalid requestId provided for task progress');\n return {};\n }\n\n try {\n const response = await fetch(\n `${this.serverUrl}/task-progress/${encodeURIComponent(requestId)}`,\n );\n\n if (!response.ok) {\n console.warn(`Task progress request failed: ${response.statusText}`);\n return {};\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to poll task progress:', error);\n return {};\n }\n }\n\n /**\n * Start polling for task progress and invoke dump update callback\n */\n private startProgressPolling(requestId: string): void {\n // Clear any existing polling\n this.stopProgressPolling();\n\n // Poll every 500ms for progress updates\n this.pollingIntervalId = setInterval(async () => {\n try {\n const progressData = await this.getTaskProgress(requestId);\n\n if (progressData.executionDump) {\n // Invoke dump update callback if set\n if (this.dumpUpdateCallback) {\n this.dumpUpdateCallback('', progressData.executionDump);\n }\n }\n } catch (error) {\n console.error('Error polling task progress:', error);\n }\n }, 500); // Poll every 500ms\n }\n\n /**\n * Stop polling for task progress\n */\n private stopProgressPolling(): void {\n if (this.pollingIntervalId) {\n clearInterval(this.pollingIntervalId);\n this.pollingIntervalId = undefined;\n }\n }\n\n // Cancel task\n async cancelTask(\n requestId: string,\n ): Promise<{ error?: string; success?: boolean }> {\n if (!this.serverUrl) {\n return { error: 'No server URL configured' };\n }\n\n if (!requestId?.trim()) {\n return { error: 'Invalid request ID' };\n }\n\n try {\n const res = await fetch(\n `${this.serverUrl}/cancel/${encodeURIComponent(requestId)}`,\n {\n method: 'POST',\n },\n );\n\n if (!res.ok) {\n return { error: `Cancel request failed: ${res.statusText}` };\n }\n\n const result = await res.json();\n return { success: true, ...result };\n } catch (error) {\n console.error('Failed to cancel task:', error);\n return { error: 'Failed to cancel task' };\n }\n }\n\n // Get screenshot from server\n async getScreenshot(): Promise<{\n screenshot: string;\n timestamp: number;\n } | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/screenshot`);\n\n if (!response.ok) {\n if (response.status !== 409) {\n console.warn(`Screenshot request failed: ${response.statusText}`);\n }\n return null;\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get screenshot:', error);\n return null;\n }\n }\n\n // Direct device manipulation – invokes a named action on the connected\n // device without going through AI planning.\n async interact(\n payload: { actionType: string } & Record<string, unknown>,\n ): Promise<{ ok: boolean; error?: string }> {\n if (!this.serverUrl) {\n return { ok: false, error: 'No server URL configured' };\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/interact`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n\n const data = (await response.json().catch(() => null)) as {\n error?: string;\n } | null;\n\n if (!response.ok) {\n return {\n ok: false,\n error: data?.error || `Interact request failed (${response.status})`,\n };\n }\n\n return { ok: true };\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async startRecorderSession(\n sessionId: string,\n ): Promise<PlaygroundRecorderStartResult> {\n if (!this.serverUrl) {\n return { ok: false, supported: false, error: 'No server URL configured' };\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/recorder/start`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId,\n }),\n });\n const data = (await response.json().catch(() => null)) as {\n ok?: boolean;\n supported?: boolean;\n source?: PlaygroundRecorderSourceKind;\n platformId?: string;\n error?: string;\n } | null;\n\n if (!response.ok) {\n return {\n ok: false,\n supported: data?.supported ?? false,\n source: data?.source,\n platformId: data?.platformId,\n error:\n data?.error || `Recorder start request failed (${response.status})`,\n };\n }\n\n return {\n ok: data?.ok ?? true,\n supported: data?.supported ?? true,\n source: data?.source,\n platformId: data?.platformId,\n error: data?.error,\n };\n } catch (error) {\n return {\n ok: false,\n supported: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async getRecorderCapabilities(): Promise<PlaygroundRecorderCapabilitiesResult> {\n if (!this.serverUrl) {\n return {\n supported: false,\n source: 'unsupported',\n error: 'No server URL configured',\n };\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/recorder/capabilities`);\n const data = (await response.json().catch(() => null)) as {\n supported?: boolean;\n source?: PlaygroundRecorderSourceKind;\n platformId?: string;\n error?: string;\n } | null;\n if (!response.ok) {\n return {\n supported: false,\n source: 'unsupported',\n error:\n data?.error ||\n `Recorder capabilities request failed (${response.status})`,\n };\n }\n return {\n supported: data?.supported === true,\n source: data?.source || 'unsupported',\n platformId: data?.platformId,\n error: data?.error,\n };\n } catch (error) {\n return {\n supported: false,\n source: 'unsupported',\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async stopRecorderSession(): Promise<{ ok: boolean; error?: string }> {\n if (!this.serverUrl) {\n return { ok: false, error: 'No server URL configured' };\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/recorder/stop`, {\n method: 'POST',\n });\n if (!response.ok) {\n return {\n ok: false,\n error: `Recorder stop request failed (${response.status})`,\n };\n }\n return { ok: true };\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async getRecorderEvents(since = 0): Promise<PlaygroundRecorderEventsResult> {\n if (!this.serverUrl) {\n return { events: [], nextIndex: since };\n }\n\n try {\n const response = await fetch(\n `${this.serverUrl}/recorder/events?since=${encodeURIComponent(String(since))}`,\n );\n if (!response.ok) {\n return { events: [], nextIndex: since };\n }\n const data = (await response.json().catch(() => null)) as {\n events?: unknown;\n nextIndex?: unknown;\n } | null;\n return {\n events: Array.isArray(data?.events) ? data.events : [],\n nextIndex:\n typeof data?.nextIndex === 'number' && Number.isFinite(data.nextIndex)\n ? data.nextIndex\n : since,\n };\n } catch (error) {\n console.error('Failed to poll recorder events:', error);\n return { events: [], nextIndex: since };\n }\n }\n\n // Get interface information from server\n async getInterfaceInfo(): Promise<{\n type: string;\n description?: string;\n size?: { width: number; height: number };\n navigationState?: { isLoading: boolean };\n actionTypes?: string[];\n } | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/interface-info`);\n\n if (!response.ok) {\n console.warn(`Interface info request failed: ${response.statusText}`);\n return null;\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get interface info:', error);\n return null;\n }\n }\n\n async getRuntimeInfo(): Promise<PlaygroundRuntimeInfo | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/runtime-info`);\n\n if (!response.ok) {\n console.warn(`Runtime info request failed: ${response.statusText}`);\n return null;\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get runtime info:', error);\n return null;\n }\n }\n\n async getSessionInfo(): Promise<PlaygroundSessionState | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/session`);\n if (!response.ok) {\n console.warn(`Session info request failed: ${response.statusText}`);\n return null;\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get session info:', error);\n return null;\n }\n }\n\n async getSessionSetup(\n input?: Record<string, unknown>,\n ): Promise<PlaygroundSessionSetup | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const searchParams = new URLSearchParams();\n Object.entries(input || {}).forEach(([key, value]) => {\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n searchParams.set(key, String(value));\n }\n });\n const suffix = searchParams.size > 0 ? `?${searchParams.toString()}` : '';\n const response = await fetch(`${this.serverUrl}/session/setup${suffix}`);\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new Error(\n body?.error || response.statusText || 'Failed to load session setup',\n );\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get session setup:', error);\n throw error;\n }\n }\n\n async listSessionTargets(): Promise<PlaygroundSessionTarget[]> {\n if (!this.serverUrl) {\n return [];\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/session/targets`);\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new Error(\n body?.error ||\n response.statusText ||\n 'Failed to load session targets',\n );\n }\n\n const result = await response.json();\n return Array.isArray(result) ? result : [];\n } catch (error) {\n console.error('Failed to get session targets:', error);\n throw error;\n }\n }\n\n async createSession(input?: Record<string, unknown>): Promise<{\n session: PlaygroundSessionState;\n runtimeInfo: PlaygroundRuntimeInfo;\n }> {\n if (!this.serverUrl) {\n throw new Error('Server URL not configured');\n }\n\n const response = await fetch(`${this.serverUrl}/session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input || {}),\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new Error(body?.error || response.statusText);\n }\n\n return await response.json();\n }\n\n async destroySession(): Promise<{\n session: PlaygroundSessionState;\n runtimeInfo: PlaygroundRuntimeInfo;\n }> {\n if (!this.serverUrl) {\n throw new Error('Server URL not configured');\n }\n\n const response = await fetch(`${this.serverUrl}/session`, {\n method: 'DELETE',\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new Error(body?.error || response.statusText);\n }\n\n return await response.json();\n }\n}\n"],"names":["RemoteExecutionAdapter","BasePlaygroundAdapter","callback","undefined","value","action","needsStructuredParams","schema","shape","missingFields","Object","key","fieldDef","isOptional","params","options","parseStructuredParams","error","message","androidErrors","androidError","keyword","actionType","window","Error","payload","response","fetch","JSON","errorText","result","console","optionalParams","optionalFields","context","Array","actionSpaceMethod","res","data","jsonError","aiConfig","body","detail","requestId","encodeURIComponent","setInterval","progressData","clearInterval","sessionId","since","String","Number","input","searchParams","URLSearchParams","suffix","serverUrl"],"mappings":"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"}
1
+ {"version":3,"file":"adapters/remote-execution.mjs","sources":["../../../src/adapters/remote-execution.ts"],"sourcesContent":["import type {\n ConnectivityTestResult,\n DeviceAction,\n ExecutionDump,\n} from '@midscene/core';\nimport { parseStructuredParams } from '../common';\nimport type {\n PlaygroundRecorderCapabilitiesResult,\n PlaygroundRecorderDescribeResult,\n PlaygroundRecorderEvent,\n PlaygroundRecorderEventsResult,\n PlaygroundRecorderSourceKind,\n PlaygroundRecorderStartResult,\n PlaygroundSessionSetup,\n PlaygroundSessionState,\n PlaygroundSessionTarget,\n} from '../platform';\nimport type { PlaygroundRuntimeInfo } from '../runtime-metadata';\nimport type { ExecutionOptions, FormValue, ValidationResult } from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class RemoteExecutionAdapter extends BasePlaygroundAdapter {\n private serverUrl?: string;\n private _id?: string;\n private dumpUpdateCallback?: (\n dump: string,\n executionDump?: ExecutionDump,\n ) => void;\n private pollingIntervalId?: ReturnType<typeof setInterval>;\n\n constructor(serverUrl: string) {\n super();\n this.serverUrl = serverUrl;\n }\n\n // Set dump update callback\n onDumpUpdate(\n callback: (dump: string, executionDump?: ExecutionDump) => void,\n ): void {\n this.dumpUpdateCallback = undefined;\n this.dumpUpdateCallback = callback;\n }\n\n // Get adapter ID (cached after first status check for remote)\n get id(): string | undefined {\n return this._id;\n }\n\n // Override validateParams for remote execution\n // Since schemas from server are JSON-serialized and lack .parse() method\n validateParams(\n value: FormValue,\n action: DeviceAction<unknown> | undefined,\n ): ValidationResult {\n if (!action?.paramSchema) {\n return { valid: true };\n }\n\n const needsStructuredParams = this.actionNeedsStructuredParams(action);\n\n if (!needsStructuredParams) {\n return { valid: true };\n }\n\n if (!value.params) {\n return { valid: false, errorMessage: 'Parameters are required' };\n }\n\n // For remote execution, perform basic validation without .parse()\n // Check if required fields are present\n if (action.paramSchema && typeof action.paramSchema === 'object') {\n const schema = action.paramSchema as any;\n if (schema.shape || schema.type === 'ZodObject') {\n const shape = schema.shape || {};\n const missingFields = Object.keys(shape).filter((key) => {\n const fieldDef = shape[key];\n // Check if field is required (not optional)\n const isOptional =\n fieldDef?.isOptional ||\n fieldDef?._def?.innerType || // ZodOptional\n fieldDef?._def?.typeName === 'ZodOptional';\n return (\n !isOptional &&\n (value.params![key] === undefined || value.params![key] === '')\n );\n });\n\n if (missingFields.length > 0) {\n return {\n valid: false,\n errorMessage: `Missing required parameters: ${missingFields.join(', ')}`,\n };\n }\n }\n }\n\n return { valid: true };\n }\n\n async parseStructuredParams(\n action: DeviceAction<unknown>,\n params: Record<string, unknown>,\n options: ExecutionOptions,\n ): Promise<unknown[]> {\n // Use shared implementation from common.ts\n return await parseStructuredParams(action, params, options);\n }\n\n formatErrorMessage(error: any): string {\n const message = error?.message || '';\n\n // Handle Android-specific errors\n const androidErrors = [\n {\n keyword: 'adb',\n message:\n 'ADB connection error. Please ensure device is connected and USB debugging is enabled.',\n },\n {\n keyword: 'UIAutomator',\n message:\n 'UIAutomator error. Please ensure the UIAutomator server is running on the device.',\n },\n ];\n\n const androidError = androidErrors.find(({ keyword }) =>\n message.includes(keyword),\n );\n if (androidError) {\n return androidError.message;\n }\n\n return this.formatBasicErrorMessage(error);\n }\n\n // Remote execution adapter - simplified interface\n async executeAction(\n actionType: string,\n value: FormValue,\n options: ExecutionOptions,\n ): Promise<unknown> {\n // If serverUrl is provided, use server-side execution\n if (this.serverUrl && typeof window !== 'undefined') {\n return this.executeViaServer(actionType, value, options);\n }\n\n throw new Error(\n 'Remote execution adapter requires server URL for execution',\n );\n }\n\n // Remote execution via server - uses same endpoint as requestPlaygroundServer\n private async executeViaServer(\n actionType: string,\n value: FormValue,\n options: ExecutionOptions,\n ): Promise<unknown> {\n const payload: Record<string, unknown> = {\n type: actionType,\n prompt: value.prompt,\n ...this.buildOptionalPayloadParams(options, value),\n };\n\n // Add context only if it exists (server can handle single agent case without context)\n if (options.context) {\n payload.context = options.context;\n }\n\n // Start polling if requestId is provided and dumpUpdateCallback is set\n if (options.requestId && this.dumpUpdateCallback) {\n this.startProgressPolling(options.requestId);\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/execute`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(\n `Server request failed (${response.status}): ${errorText}`,\n );\n }\n\n const result = await response.json();\n\n return result;\n } catch (error) {\n console.error('Execute via server failed:', error);\n throw error;\n } finally {\n // Stop polling when execution completes (success or error)\n this.stopProgressPolling();\n }\n }\n\n // Helper method to build optional payload parameters\n private buildOptionalPayloadParams(\n options: ExecutionOptions,\n value: FormValue,\n ): Record<string, unknown> {\n const optionalParams: Record<string, unknown> = {};\n\n // Add optional parameters only if they have meaningful values\n const optionalFields = [\n { key: 'requestId', value: options.requestId },\n { key: 'deepLocate', value: options.deepLocate },\n { key: 'deepThink', value: options.deepThink },\n { key: 'screenshotIncluded', value: options.screenshotIncluded },\n { key: 'domIncluded', value: options.domIncluded },\n { key: 'deviceOptions', value: options.deviceOptions },\n { key: 'reportDisplay', value: options.reportDisplay },\n { key: 'params', value: value.params },\n ] as const;\n\n optionalFields.forEach(({ key, value }) => {\n if (value !== undefined && value !== null && value !== '') {\n optionalParams[key] = value;\n }\n });\n\n return optionalParams;\n }\n\n // Get action space from server with fallback\n async getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]> {\n // Try server first if available\n if (this.serverUrl && typeof window !== 'undefined') {\n try {\n const response = await fetch(`${this.serverUrl}/action-space`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ context }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get action space: ${response.statusText}`);\n }\n\n const result = await response.json();\n return Array.isArray(result) ? result : [];\n } catch (error) {\n console.error('Failed to get action space from server:', error);\n // Fall through to context fallback\n }\n }\n\n // Fallback: try context.actionSpace if available\n if (context && typeof context === 'object' && 'actionSpace' in context) {\n try {\n const actionSpaceMethod = (\n context as {\n actionSpace: () =>\n | DeviceAction<unknown>[]\n | Promise<DeviceAction<unknown>[]>;\n }\n ).actionSpace;\n const result = await actionSpaceMethod();\n return Array.isArray(result) ? result : [];\n } catch (error) {\n console.error('Failed to get action space from context:', error);\n }\n }\n\n return [];\n }\n\n // Uses base implementation for validateParams and createDisplayContent\n\n // Server communication methods\n async checkStatus(): Promise<boolean> {\n if (!this.serverUrl) {\n return false;\n }\n\n try {\n const res = await fetch(`${this.serverUrl}/status`);\n if (res.status === 200) {\n // Try to extract id from response\n try {\n const data = await res.json();\n if (data.id && typeof data.id === 'string') {\n this._id = data.id;\n }\n } catch (jsonError) {\n // If JSON parsing fails, id remains undefined but status is still OK\n console.debug('Failed to parse status response:', jsonError);\n }\n return true;\n }\n return false;\n } catch (error) {\n console.warn('Server status check failed:', error);\n return false;\n }\n }\n\n async overrideConfig(aiConfig: Record<string, unknown>): Promise<void> {\n if (!this.serverUrl) {\n throw new Error('Server URL not configured');\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/config`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ aiConfig }),\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n const detail = body?.error || response.statusText;\n throw new Error(detail);\n }\n } catch (error) {\n console.error('Failed to override server config:', error);\n throw error;\n }\n }\n\n async runConnectivityTest(): Promise<ConnectivityTestResult> {\n if (!this.serverUrl) {\n throw new Error('Server URL not configured');\n }\n\n const response = await fetch(`${this.serverUrl}/connectivity-test`, {\n method: 'POST',\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n const detail = body?.error || response.statusText;\n throw new Error(detail);\n }\n\n return response.json();\n }\n\n async getTaskProgress(requestId: string): Promise<{\n executionDump?: ExecutionDump;\n }> {\n if (!this.serverUrl) {\n return {};\n }\n\n if (!requestId?.trim()) {\n console.warn('Invalid requestId provided for task progress');\n return {};\n }\n\n try {\n const response = await fetch(\n `${this.serverUrl}/task-progress/${encodeURIComponent(requestId)}`,\n );\n\n if (!response.ok) {\n console.warn(`Task progress request failed: ${response.statusText}`);\n return {};\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to poll task progress:', error);\n return {};\n }\n }\n\n /**\n * Start polling for task progress and invoke dump update callback\n */\n private startProgressPolling(requestId: string): void {\n // Clear any existing polling\n this.stopProgressPolling();\n\n // Poll every 500ms for progress updates\n this.pollingIntervalId = setInterval(async () => {\n try {\n const progressData = await this.getTaskProgress(requestId);\n\n if (progressData.executionDump) {\n // Invoke dump update callback if set\n if (this.dumpUpdateCallback) {\n this.dumpUpdateCallback('', progressData.executionDump);\n }\n }\n } catch (error) {\n console.error('Error polling task progress:', error);\n }\n }, 500); // Poll every 500ms\n }\n\n /**\n * Stop polling for task progress\n */\n private stopProgressPolling(): void {\n if (this.pollingIntervalId) {\n clearInterval(this.pollingIntervalId);\n this.pollingIntervalId = undefined;\n }\n }\n\n // Cancel task\n async cancelTask(\n requestId: string,\n ): Promise<{ error?: string; success?: boolean }> {\n if (!this.serverUrl) {\n return { error: 'No server URL configured' };\n }\n\n if (!requestId?.trim()) {\n return { error: 'Invalid request ID' };\n }\n\n try {\n const res = await fetch(\n `${this.serverUrl}/cancel/${encodeURIComponent(requestId)}`,\n {\n method: 'POST',\n },\n );\n\n if (!res.ok) {\n return { error: `Cancel request failed: ${res.statusText}` };\n }\n\n const result = await res.json();\n return { success: true, ...result };\n } catch (error) {\n console.error('Failed to cancel task:', error);\n return { error: 'Failed to cancel task' };\n }\n }\n\n // Get screenshot from server\n async getScreenshot(): Promise<{\n screenshot: string;\n timestamp: number;\n } | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/screenshot`);\n\n if (!response.ok) {\n if (response.status !== 409) {\n console.warn(`Screenshot request failed: ${response.statusText}`);\n }\n return null;\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get screenshot:', error);\n return null;\n }\n }\n\n // Direct device manipulation – invokes a named action on the connected\n // device without going through AI planning.\n async interact(\n payload: { actionType: string } & Record<string, unknown>,\n ): Promise<{ ok: boolean; error?: string }> {\n if (!this.serverUrl) {\n return { ok: false, error: 'No server URL configured' };\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/interact`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n\n const data = (await response.json().catch(() => null)) as {\n error?: string;\n } | null;\n\n if (!response.ok) {\n return {\n ok: false,\n error: data?.error || `Interact request failed (${response.status})`,\n };\n }\n\n return { ok: true };\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async startRecorderSession(\n sessionId: string,\n ): Promise<PlaygroundRecorderStartResult> {\n if (!this.serverUrl) {\n return { ok: false, supported: false, error: 'No server URL configured' };\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/recorder/start`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId,\n }),\n });\n const data = (await response.json().catch(() => null)) as {\n ok?: boolean;\n supported?: boolean;\n source?: PlaygroundRecorderSourceKind;\n platformId?: string;\n error?: string;\n } | null;\n\n if (!response.ok) {\n return {\n ok: false,\n supported: data?.supported ?? false,\n source: data?.source,\n platformId: data?.platformId,\n error:\n data?.error || `Recorder start request failed (${response.status})`,\n };\n }\n\n return {\n ok: data?.ok ?? true,\n supported: data?.supported ?? true,\n source: data?.source,\n platformId: data?.platformId,\n error: data?.error,\n };\n } catch (error) {\n return {\n ok: false,\n supported: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async getRecorderCapabilities(): Promise<PlaygroundRecorderCapabilitiesResult> {\n if (!this.serverUrl) {\n return {\n supported: false,\n source: 'unsupported',\n error: 'No server URL configured',\n };\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/recorder/capabilities`);\n const data = (await response.json().catch(() => null)) as {\n supported?: boolean;\n source?: PlaygroundRecorderSourceKind;\n platformId?: string;\n error?: string;\n } | null;\n if (!response.ok) {\n return {\n supported: false,\n source: 'unsupported',\n error:\n data?.error ||\n `Recorder capabilities request failed (${response.status})`,\n };\n }\n return {\n supported: data?.supported === true,\n source: data?.source || 'unsupported',\n platformId: data?.platformId,\n error: data?.error,\n };\n } catch (error) {\n return {\n supported: false,\n source: 'unsupported',\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async stopRecorderSession(): Promise<{ ok: boolean; error?: string }> {\n if (!this.serverUrl) {\n return { ok: false, error: 'No server URL configured' };\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/recorder/stop`, {\n method: 'POST',\n });\n if (!response.ok) {\n return {\n ok: false,\n error: `Recorder stop request failed (${response.status})`,\n };\n }\n return { ok: true };\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n async getRecorderEvents(since = 0): Promise<PlaygroundRecorderEventsResult> {\n if (!this.serverUrl) {\n return { events: [], nextIndex: since };\n }\n\n try {\n const response = await fetch(\n `${this.serverUrl}/recorder/events?since=${encodeURIComponent(String(since))}`,\n );\n if (!response.ok) {\n return { events: [], nextIndex: since };\n }\n const data = (await response.json().catch(() => null)) as {\n events?: unknown;\n nextIndex?: unknown;\n } | null;\n return {\n events: Array.isArray(data?.events) ? data.events : [],\n nextIndex:\n typeof data?.nextIndex === 'number' && Number.isFinite(data.nextIndex)\n ? data.nextIndex\n : since,\n };\n } catch (error) {\n console.error('Failed to poll recorder events:', error);\n return { events: [], nextIndex: since };\n }\n }\n\n async describeRecorderEventAtPoint(\n event: PlaygroundRecorderEvent,\n ): Promise<PlaygroundRecorderDescribeResult> {\n if (!this.serverUrl) {\n return { ok: false, error: 'No server URL configured' };\n }\n\n try {\n const response = await fetch(\n `${this.serverUrl}/recorder/describe-event`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ event }),\n },\n );\n const data = (await response\n .json()\n .catch(() => null)) as PlaygroundRecorderDescribeResult | null;\n if (!response.ok) {\n return {\n ok: false,\n error:\n data?.error ||\n `Recorder describe request failed (${response.status})`,\n };\n }\n return data || { ok: false, error: 'Empty recorder describe response' };\n } catch (error) {\n return {\n ok: false,\n error:\n error instanceof Error\n ? error.message\n : 'Failed to describe recorder event',\n };\n }\n }\n\n // Get interface information from server\n async getInterfaceInfo(): Promise<{\n type: string;\n description?: string;\n size?: { width: number; height: number };\n navigationState?: { isLoading: boolean };\n actionTypes?: string[];\n } | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/interface-info`);\n\n if (!response.ok) {\n console.warn(`Interface info request failed: ${response.statusText}`);\n return null;\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get interface info:', error);\n return null;\n }\n }\n\n async getRuntimeInfo(): Promise<PlaygroundRuntimeInfo | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/runtime-info`);\n\n if (!response.ok) {\n console.warn(`Runtime info request failed: ${response.statusText}`);\n return null;\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get runtime info:', error);\n return null;\n }\n }\n\n async getSessionInfo(): Promise<PlaygroundSessionState | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/session`);\n if (!response.ok) {\n console.warn(`Session info request failed: ${response.statusText}`);\n return null;\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get session info:', error);\n return null;\n }\n }\n\n async getSessionSetup(\n input?: Record<string, unknown>,\n ): Promise<PlaygroundSessionSetup | null> {\n if (!this.serverUrl) {\n return null;\n }\n\n try {\n const searchParams = new URLSearchParams();\n Object.entries(input || {}).forEach(([key, value]) => {\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n searchParams.set(key, String(value));\n }\n });\n const suffix = searchParams.size > 0 ? `?${searchParams.toString()}` : '';\n const response = await fetch(`${this.serverUrl}/session/setup${suffix}`);\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new Error(\n body?.error || response.statusText || 'Failed to load session setup',\n );\n }\n\n return await response.json();\n } catch (error) {\n console.error('Failed to get session setup:', error);\n throw error;\n }\n }\n\n async listSessionTargets(): Promise<PlaygroundSessionTarget[]> {\n if (!this.serverUrl) {\n return [];\n }\n\n try {\n const response = await fetch(`${this.serverUrl}/session/targets`);\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new Error(\n body?.error ||\n response.statusText ||\n 'Failed to load session targets',\n );\n }\n\n const result = await response.json();\n return Array.isArray(result) ? result : [];\n } catch (error) {\n console.error('Failed to get session targets:', error);\n throw error;\n }\n }\n\n async createSession(input?: Record<string, unknown>): Promise<{\n session: PlaygroundSessionState;\n runtimeInfo: PlaygroundRuntimeInfo;\n }> {\n if (!this.serverUrl) {\n throw new Error('Server URL not configured');\n }\n\n const response = await fetch(`${this.serverUrl}/session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input || {}),\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new Error(body?.error || response.statusText);\n }\n\n return await response.json();\n }\n\n async destroySession(): Promise<{\n session: PlaygroundSessionState;\n runtimeInfo: PlaygroundRuntimeInfo;\n }> {\n if (!this.serverUrl) {\n throw new Error('Server URL not configured');\n }\n\n const response = await fetch(`${this.serverUrl}/session`, {\n method: 'DELETE',\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n throw new Error(body?.error || response.statusText);\n }\n\n return await response.json();\n }\n}\n"],"names":["RemoteExecutionAdapter","BasePlaygroundAdapter","callback","undefined","value","action","needsStructuredParams","schema","shape","missingFields","Object","key","fieldDef","isOptional","params","options","parseStructuredParams","error","message","androidErrors","androidError","keyword","actionType","window","Error","payload","response","fetch","JSON","errorText","result","console","optionalParams","optionalFields","context","Array","actionSpaceMethod","res","data","jsonError","aiConfig","body","detail","requestId","encodeURIComponent","setInterval","progressData","clearInterval","sessionId","since","String","Number","event","input","searchParams","URLSearchParams","suffix","serverUrl"],"mappings":"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"}
@@ -15,6 +15,24 @@ const noReplayAPIs = [
15
15
  ...dataExtractionAPIs,
16
16
  ...validationAPIs
17
17
  ];
18
+ const agentPromptAPIs = [
19
+ 'aiAct',
20
+ 'runMarkdown',
21
+ 'aiQuery',
22
+ 'aiBoolean',
23
+ 'aiNumber',
24
+ 'aiString',
25
+ 'aiAsk',
26
+ 'aiWaitFor'
27
+ ];
28
+ const agentPromptAPISet = new Set(agentPromptAPIs);
29
+ function getAgentPromptAPI(activeAgent, actionType) {
30
+ if (!agentPromptAPISet.has(actionType)) return;
31
+ const methodName = actionType;
32
+ const method = activeAgent[methodName];
33
+ if ('function' != typeof method) return;
34
+ return async (prompt, options)=>method.call(activeAgent, prompt || '', options);
35
+ }
18
36
  const formatErrorMessage = (e)=>{
19
37
  const errorMessage = e?.message || '';
20
38
  if (errorMessage.includes('of different extension')) return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';
@@ -128,7 +146,7 @@ async function executeAction(activeAgent, actionType, actionSpace, value, option
128
146
  deepLocate: options.deepLocate,
129
147
  cacheable: true
130
148
  }) : void 0;
131
- const { deviceOptions: _, ...optionsWithoutDeviceOptions } = options;
149
+ const { deviceOptions: _, reportDisplay: __, ...optionsWithoutDeviceOptions } = options;
132
150
  const actionParams = {
133
151
  locate: detailedLocateParam,
134
152
  ...optionsWithoutDeviceOptions,
@@ -139,16 +157,25 @@ async function executeAction(activeAgent, actionType, actionSpace, value, option
139
157
  {
140
158
  const prompt = value.prompt;
141
159
  if ('aiAssert' === actionType) {
160
+ const { reportDisplay: _reportDisplay, ...optionsWithoutReportDisplay } = options;
142
161
  const { pass, thought } = await activeAgent?.aiAssert?.(prompt || '', void 0, {
143
162
  keepRawResponse: true,
144
- ...options
163
+ ...optionsWithoutReportDisplay
145
164
  }) || {};
146
165
  return {
147
166
  pass: pass || false,
148
167
  thought: thought || ''
149
168
  };
150
169
  }
151
- if (activeAgent && 'function' == typeof activeAgent[actionType]) return await activeAgent[actionType](prompt, options);
170
+ const agentPromptAPI = getAgentPromptAPI(activeAgent, actionType);
171
+ if (agentPromptAPI) {
172
+ const { reportDisplay, ...agentOptions } = options;
173
+ const optionsForAgent = reportDisplay ? {
174
+ ...agentOptions,
175
+ _internalReportDisplay: reportDisplay
176
+ } : agentOptions;
177
+ return await agentPromptAPI(prompt, optionsForAgent);
178
+ }
152
179
  throw new Error(`Unknown action type: ${actionType}`);
153
180
  }
154
181
  }
@@ -1 +1 @@
1
- {"version":3,"file":"common.mjs","sources":["../../src/common.ts"],"sourcesContent":["import type { DeviceAction } from '@midscene/core';\nimport { findAllMidsceneLocatorField } from '@midscene/core/ai-model';\nimport { buildDetailedLocateParam } from '@midscene/core/yaml';\nimport type {\n ExecutionOptions,\n FormValue,\n PlaygroundAgent,\n ValidationResult,\n} from './types';\n\n// APIs that should not generate replay scripts\nexport const dataExtractionAPIs = [\n 'aiQuery',\n 'aiBoolean',\n 'aiNumber',\n 'aiString',\n 'aiAsk',\n];\n\nexport const validationAPIs = ['aiAssert', 'aiWaitFor'];\n\nexport const noReplayAPIs = [...dataExtractionAPIs, ...validationAPIs];\n\nexport const formatErrorMessage = (e: any): string => {\n const errorMessage = e?.message || '';\n\n if (errorMessage.includes('of different extension')) {\n return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';\n }\n\n if (errorMessage.includes('NOT_IMPLEMENTED_AS_DESIGNED')) {\n return 'Further actions cannot be performed in the current environment';\n }\n\n return errorMessage || 'Unknown error';\n};\n\n// Parse structured parameters for callActionInActionSpace\nexport async function parseStructuredParams(\n action: DeviceAction<unknown>,\n params: Record<string, unknown>,\n options: ExecutionOptions = {},\n): Promise<unknown[]> {\n if (!action?.paramSchema || !('shape' in action.paramSchema)) {\n return [params.prompt || '', options];\n }\n\n const schema = action.paramSchema;\n const keys =\n schema && 'shape' in schema\n ? Object.keys((schema as { shape: Record<string, unknown> }).shape)\n : [];\n\n // Start with options and merge deviceOptions into the same level\n // Destructure to exclude deviceOptions from the final object\n const { deviceOptions: _, ...optionsWithoutDeviceOptions } = options;\n const paramObj: Record<string, unknown> = {\n ...optionsWithoutDeviceOptions,\n ...(options.deviceOptions || {}),\n };\n\n keys.forEach((key) => {\n if (\n params[key] !== undefined &&\n params[key] !== null &&\n params[key] !== ''\n ) {\n paramObj[key] = params[key];\n }\n });\n\n // Check if there's a locate field that needs detailed locate param processing\n if (schema) {\n const locatorFieldKeys = findAllMidsceneLocatorField(schema);\n locatorFieldKeys.forEach((locateKey: string) => {\n const locatePrompt = params[locateKey];\n if (locatePrompt && typeof locatePrompt === 'string') {\n // Build detailed locate param using the locate prompt and options\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, {\n deepLocate: options.deepLocate,\n cacheable: true, // Default to true for playground\n });\n if (detailedLocateParam) {\n paramObj[locateKey] = detailedLocateParam;\n }\n }\n });\n }\n\n return [paramObj];\n}\n\nexport function validateStructuredParams(\n value: FormValue,\n action: DeviceAction<unknown> | undefined,\n): ValidationResult {\n if (!value.params) {\n return { valid: false, errorMessage: 'Parameters are required' };\n }\n\n if (!action?.paramSchema) {\n return { valid: true };\n }\n\n try {\n const paramsForValidation = { ...value.params };\n\n const schema = action.paramSchema;\n if (schema) {\n const locatorFieldKeys = findAllMidsceneLocatorField(schema);\n locatorFieldKeys.forEach((key: string) => {\n if (typeof paramsForValidation[key] === 'string') {\n paramsForValidation[key] = {\n midscene_location_field_flag: true,\n prompt: paramsForValidation[key],\n center: [0, 0],\n rect: { left: 0, top: 0, width: 0, height: 0 },\n };\n }\n });\n }\n\n action.paramSchema?.parse(paramsForValidation);\n return { valid: true };\n } catch (error: unknown) {\n const zodError = error as {\n errors?: Array<{ path: string[]; message: string }>;\n };\n if (zodError.errors && zodError.errors.length > 0) {\n const errorMessages = zodError.errors\n .filter((err) => {\n const path = err.path.join('.');\n return (\n !path.includes('center') &&\n !path.includes('rect') &&\n !path.includes('midscene_location_field_flag')\n );\n })\n .map((err) => {\n const field = err.path.join('.');\n return `${field}: ${err.message}`;\n });\n\n if (errorMessages.length > 0) {\n return {\n valid: false,\n errorMessage: `Validation error: ${errorMessages.join(', ')}`,\n };\n }\n } else {\n const errorMsg =\n error instanceof Error ? error.message : 'Unknown validation error';\n return {\n valid: false,\n errorMessage: `Parameter validation failed: ${errorMsg}`,\n };\n }\n }\n\n return { valid: true };\n}\n\nexport async function executeAction(\n activeAgent: PlaygroundAgent,\n actionType: string,\n actionSpace: DeviceAction<unknown>[],\n value: FormValue,\n options: ExecutionOptions,\n): Promise<unknown> {\n const canForwardDeepThink =\n actionType === 'aiAct' || actionType === 'runMarkdown';\n if (!canForwardDeepThink && options.deepThink !== undefined) {\n console.warn(\n '[Playground] Received deepThink in non-aiAct action options. deepThink is expected to be used with aiAct/runMarkdown during migration.',\n {\n actionType,\n requestId: options.requestId,\n options,\n },\n );\n }\n\n const action = actionSpace?.find(\n (a: DeviceAction<unknown>) =>\n a.interfaceAlias === actionType || a.name === actionType,\n );\n\n if (action && typeof activeAgent.callActionInActionSpace === 'function') {\n if (value.params) {\n const parsedParams = await parseStructuredParams(\n action,\n value.params,\n options,\n );\n return await activeAgent.callActionInActionSpace(\n action.name,\n parsedParams[0],\n );\n } else {\n // For prompt-based actions, we need to build the detailed locate param\n const detailedLocateParam = value.prompt\n ? buildDetailedLocateParam(value.prompt, {\n deepLocate: options.deepLocate,\n cacheable: true,\n })\n : undefined;\n\n // Flatten deviceOptions into the params\n // Destructure to exclude deviceOptions from the final object\n const { deviceOptions: _, ...optionsWithoutDeviceOptions } = options;\n const actionParams = {\n locate: detailedLocateParam,\n ...optionsWithoutDeviceOptions,\n ...(options.deviceOptions || {}),\n };\n\n return await activeAgent.callActionInActionSpace(\n action.name,\n actionParams,\n );\n }\n } else {\n const prompt = value.prompt;\n\n if (actionType === 'aiAssert') {\n const { pass, thought } =\n (await activeAgent?.aiAssert?.(prompt || '', undefined, {\n keepRawResponse: true,\n ...options,\n })) || {};\n return { pass: pass || false, thought: thought || '' };\n }\n\n // Fallback for methods not found in actionSpace\n if (activeAgent && typeof activeAgent[actionType] === 'function') {\n return await activeAgent[actionType](prompt, options);\n }\n\n throw new Error(`Unknown action type: ${actionType}`);\n }\n}\n"],"names":["dataExtractionAPIs","validationAPIs","noReplayAPIs","formatErrorMessage","e","errorMessage","parseStructuredParams","action","params","options","schema","keys","Object","_","optionsWithoutDeviceOptions","paramObj","key","undefined","locatorFieldKeys","findAllMidsceneLocatorField","locateKey","locatePrompt","detailedLocateParam","buildDetailedLocateParam","validateStructuredParams","value","paramsForValidation","error","zodError","errorMessages","err","path","field","errorMsg","Error","executeAction","activeAgent","actionType","actionSpace","canForwardDeepThink","console","a","parsedParams","actionParams","prompt","pass","thought"],"mappings":"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"}
1
+ {"version":3,"file":"common.mjs","sources":["../../src/common.ts"],"sourcesContent":["import type { DeviceAction } from '@midscene/core';\nimport { findAllMidsceneLocatorField } from '@midscene/core/ai-model';\nimport { buildDetailedLocateParam } from '@midscene/core/yaml';\nimport type {\n ExecutionOptions,\n FormValue,\n PlaygroundAgent,\n ValidationResult,\n} from './types';\n\n// APIs that should not generate replay scripts\nexport const dataExtractionAPIs = [\n 'aiQuery',\n 'aiBoolean',\n 'aiNumber',\n 'aiString',\n 'aiAsk',\n];\n\nexport const validationAPIs = ['aiAssert', 'aiWaitFor'];\n\nexport const noReplayAPIs = [...dataExtractionAPIs, ...validationAPIs];\n\nconst agentPromptAPIs = [\n 'aiAct',\n 'runMarkdown',\n 'aiQuery',\n 'aiBoolean',\n 'aiNumber',\n 'aiString',\n 'aiAsk',\n 'aiWaitFor',\n] as const;\n\ntype AgentPromptAPI = (typeof agentPromptAPIs)[number];\n\nconst agentPromptAPISet = new Set<string>(agentPromptAPIs);\n\nfunction getAgentPromptAPI(\n activeAgent: PlaygroundAgent,\n actionType: string,\n):\n | ((\n prompt: string | undefined,\n options: ExecutionOptions,\n ) => Promise<unknown>)\n | undefined {\n if (!agentPromptAPISet.has(actionType)) {\n return undefined;\n }\n\n const methodName = actionType as AgentPromptAPI;\n const method = activeAgent[methodName] as unknown;\n if (typeof method !== 'function') {\n return undefined;\n }\n\n return async (prompt, options) =>\n (\n method as (prompt: string, options: ExecutionOptions) => Promise<unknown>\n ).call(activeAgent, prompt || '', options);\n}\n\nexport const formatErrorMessage = (e: any): string => {\n const errorMessage = e?.message || '';\n\n if (errorMessage.includes('of different extension')) {\n return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';\n }\n\n if (errorMessage.includes('NOT_IMPLEMENTED_AS_DESIGNED')) {\n return 'Further actions cannot be performed in the current environment';\n }\n\n return errorMessage || 'Unknown error';\n};\n\n// Parse structured parameters for callActionInActionSpace\nexport async function parseStructuredParams(\n action: DeviceAction<unknown>,\n params: Record<string, unknown>,\n options: ExecutionOptions = {},\n): Promise<unknown[]> {\n if (!action?.paramSchema || !('shape' in action.paramSchema)) {\n return [params.prompt || '', options];\n }\n\n const schema = action.paramSchema;\n const keys =\n schema && 'shape' in schema\n ? Object.keys((schema as { shape: Record<string, unknown> }).shape)\n : [];\n\n // Start with options and merge deviceOptions into the same level\n // Destructure to exclude deviceOptions from the final object\n const { deviceOptions: _, ...optionsWithoutDeviceOptions } = options;\n const paramObj: Record<string, unknown> = {\n ...optionsWithoutDeviceOptions,\n ...(options.deviceOptions || {}),\n };\n\n keys.forEach((key) => {\n if (\n params[key] !== undefined &&\n params[key] !== null &&\n params[key] !== ''\n ) {\n paramObj[key] = params[key];\n }\n });\n\n // Check if there's a locate field that needs detailed locate param processing\n if (schema) {\n const locatorFieldKeys = findAllMidsceneLocatorField(schema);\n locatorFieldKeys.forEach((locateKey: string) => {\n const locatePrompt = params[locateKey];\n if (locatePrompt && typeof locatePrompt === 'string') {\n // Build detailed locate param using the locate prompt and options\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, {\n deepLocate: options.deepLocate,\n cacheable: true, // Default to true for playground\n });\n if (detailedLocateParam) {\n paramObj[locateKey] = detailedLocateParam;\n }\n }\n });\n }\n\n return [paramObj];\n}\n\nexport function validateStructuredParams(\n value: FormValue,\n action: DeviceAction<unknown> | undefined,\n): ValidationResult {\n if (!value.params) {\n return { valid: false, errorMessage: 'Parameters are required' };\n }\n\n if (!action?.paramSchema) {\n return { valid: true };\n }\n\n try {\n const paramsForValidation = { ...value.params };\n\n const schema = action.paramSchema;\n if (schema) {\n const locatorFieldKeys = findAllMidsceneLocatorField(schema);\n locatorFieldKeys.forEach((key: string) => {\n if (typeof paramsForValidation[key] === 'string') {\n paramsForValidation[key] = {\n midscene_location_field_flag: true,\n prompt: paramsForValidation[key],\n center: [0, 0],\n rect: { left: 0, top: 0, width: 0, height: 0 },\n };\n }\n });\n }\n\n action.paramSchema?.parse(paramsForValidation);\n return { valid: true };\n } catch (error: unknown) {\n const zodError = error as {\n errors?: Array<{ path: string[]; message: string }>;\n };\n if (zodError.errors && zodError.errors.length > 0) {\n const errorMessages = zodError.errors\n .filter((err) => {\n const path = err.path.join('.');\n return (\n !path.includes('center') &&\n !path.includes('rect') &&\n !path.includes('midscene_location_field_flag')\n );\n })\n .map((err) => {\n const field = err.path.join('.');\n return `${field}: ${err.message}`;\n });\n\n if (errorMessages.length > 0) {\n return {\n valid: false,\n errorMessage: `Validation error: ${errorMessages.join(', ')}`,\n };\n }\n } else {\n const errorMsg =\n error instanceof Error ? error.message : 'Unknown validation error';\n return {\n valid: false,\n errorMessage: `Parameter validation failed: ${errorMsg}`,\n };\n }\n }\n\n return { valid: true };\n}\n\nexport async function executeAction(\n activeAgent: PlaygroundAgent,\n actionType: string,\n actionSpace: DeviceAction<unknown>[],\n value: FormValue,\n options: ExecutionOptions,\n): Promise<unknown> {\n const canForwardDeepThink =\n actionType === 'aiAct' || actionType === 'runMarkdown';\n if (!canForwardDeepThink && options.deepThink !== undefined) {\n console.warn(\n '[Playground] Received deepThink in non-aiAct action options. deepThink is expected to be used with aiAct/runMarkdown during migration.',\n {\n actionType,\n requestId: options.requestId,\n options,\n },\n );\n }\n\n const action = actionSpace?.find(\n (a: DeviceAction<unknown>) =>\n a.interfaceAlias === actionType || a.name === actionType,\n );\n\n if (action && typeof activeAgent.callActionInActionSpace === 'function') {\n if (value.params) {\n const parsedParams = await parseStructuredParams(\n action,\n value.params,\n options,\n );\n return await activeAgent.callActionInActionSpace(\n action.name,\n parsedParams[0],\n );\n } else {\n // For prompt-based actions, we need to build the detailed locate param\n const detailedLocateParam = value.prompt\n ? buildDetailedLocateParam(value.prompt, {\n deepLocate: options.deepLocate,\n cacheable: true,\n })\n : undefined;\n\n // Flatten deviceOptions into the params\n // Destructure to exclude deviceOptions from the final object\n const {\n deviceOptions: _,\n reportDisplay: __,\n ...optionsWithoutDeviceOptions\n } = options;\n const actionParams = {\n locate: detailedLocateParam,\n ...optionsWithoutDeviceOptions,\n ...(options.deviceOptions || {}),\n };\n\n return await activeAgent.callActionInActionSpace(\n action.name,\n actionParams,\n );\n }\n } else {\n const prompt = value.prompt;\n\n if (actionType === 'aiAssert') {\n const { reportDisplay: _reportDisplay, ...optionsWithoutReportDisplay } =\n options;\n const { pass, thought } =\n (await activeAgent?.aiAssert?.(prompt || '', undefined, {\n keepRawResponse: true,\n ...optionsWithoutReportDisplay,\n })) || {};\n return { pass: pass || false, thought: thought || '' };\n }\n\n const agentPromptAPI = getAgentPromptAPI(activeAgent, actionType);\n if (agentPromptAPI) {\n const { reportDisplay, ...agentOptions } = options;\n const optionsForAgent = reportDisplay\n ? {\n ...agentOptions,\n _internalReportDisplay: reportDisplay,\n }\n : agentOptions;\n return await agentPromptAPI(prompt, optionsForAgent);\n }\n\n throw new Error(`Unknown action type: ${actionType}`);\n }\n}\n"],"names":["dataExtractionAPIs","validationAPIs","noReplayAPIs","agentPromptAPIs","agentPromptAPISet","Set","getAgentPromptAPI","activeAgent","actionType","methodName","method","prompt","options","formatErrorMessage","e","errorMessage","parseStructuredParams","action","params","schema","keys","Object","_","optionsWithoutDeviceOptions","paramObj","key","undefined","locatorFieldKeys","findAllMidsceneLocatorField","locateKey","locatePrompt","detailedLocateParam","buildDetailedLocateParam","validateStructuredParams","value","paramsForValidation","error","zodError","errorMessages","err","path","field","errorMsg","Error","executeAction","actionSpace","canForwardDeepThink","console","a","parsedParams","__","actionParams","_reportDisplay","optionsWithoutReportDisplay","pass","thought","agentPromptAPI","reportDisplay","agentOptions","optionsForAgent"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.mjs","sources":["../../src/index.browser.ts"],"sourcesContent":["// Browser-safe version of playground exports (excludes server)\nexport {\n dataExtractionAPIs,\n noReplayAPIs,\n validationAPIs,\n formatErrorMessage,\n validateStructuredParams,\n executeAction,\n} from './common';\n\n// SDK exports (all browser-safe)\nexport { PlaygroundSDK } from './sdk/index';\nexport { BasePlaygroundAdapter } from './adapters/base';\nexport { LocalExecutionAdapter } from './adapters/local-execution';\nexport { RemoteExecutionAdapter } from './adapters/remote-execution';\nexport {\n createMjpegPreviewDescriptor,\n createScreenshotPreviewDescriptor,\n createScrcpyPreviewDescriptor,\n definePlaygroundPlatform,\n resolvePreparedLaunchOptions,\n} from './platform';\n\n// PlaygroundServer is not available in browser environments\nexport const PlaygroundServer = undefined;\nexport const playgroundForAgent = undefined;\nexport const playgroundForAgentFactory = undefined;\nexport const playgroundForSessionManager = undefined;\nexport const launchPreparedPlaygroundPlatform = undefined;\n\nexport type {\n PlaygroundInteractPayload,\n PlaygroundInteractResult,\n PlaygroundPageRecordedEvent,\n} from './sdk/index';\nexport type {\n BeforeActionHook,\n ExecutionOptions,\n FormValue,\n PlaygroundAgent,\n ValidationResult,\n PlaygroundConfig,\n ExecutionType,\n PlaygroundAdapter,\n} from './types';\nexport type {\n PlaygroundCreatedSession,\n PlaygroundExecutionHooks,\n PlaygroundPlatformRegistration,\n PlaygroundPlatformDescriptor,\n PlaygroundPlatformSelectorConfig,\n PlaygroundPreviewCapability,\n PlaygroundPreviewDescriptor,\n PlaygroundPreviewKind,\n PlaygroundRecorderCapabilitiesResult,\n PlaygroundRecorderEvent,\n PlaygroundRecorderEventsResult,\n PlaygroundRecorderSourceKind,\n PlaygroundRecorderStartResult,\n PlaygroundSidecar,\n PreparedPlaygroundPlatform,\n PlaygroundSessionField,\n PlaygroundSessionFieldOption,\n PlaygroundSessionManager,\n PlaygroundSessionSetup,\n PlaygroundSessionState,\n PlaygroundSessionTarget,\n} from './platform';\nexport type { PlaygroundRuntimeInfo } from './runtime-metadata';\n"],"names":["PlaygroundServer","undefined","playgroundForAgent","playgroundForAgentFactory","playgroundForSessionManager","launchPreparedPlaygroundPlatform"],"mappings":";;;;;;AAwBO,MAAMA,mBAAmBC;AACzB,MAAMC,qBAAqBD;AAC3B,MAAME,4BAA4BF;AAClC,MAAMG,8BAA8BH;AACpC,MAAMI,mCAAmCJ"}
1
+ {"version":3,"file":"index.browser.mjs","sources":["../../src/index.browser.ts"],"sourcesContent":["// Browser-safe version of playground exports (excludes server)\nexport {\n dataExtractionAPIs,\n noReplayAPIs,\n validationAPIs,\n formatErrorMessage,\n validateStructuredParams,\n executeAction,\n} from './common';\n\n// SDK exports (all browser-safe)\nexport { PlaygroundSDK } from './sdk/index';\nexport { BasePlaygroundAdapter } from './adapters/base';\nexport { LocalExecutionAdapter } from './adapters/local-execution';\nexport { RemoteExecutionAdapter } from './adapters/remote-execution';\nexport {\n createMjpegPreviewDescriptor,\n createScreenshotPreviewDescriptor,\n createScrcpyPreviewDescriptor,\n definePlaygroundPlatform,\n resolvePreparedLaunchOptions,\n} from './platform';\n\n// PlaygroundServer is not available in browser environments\nexport const PlaygroundServer = undefined;\nexport const playgroundForAgent = undefined;\nexport const playgroundForAgentFactory = undefined;\nexport const playgroundForSessionManager = undefined;\nexport const launchPreparedPlaygroundPlatform = undefined;\n\nexport type {\n PlaygroundInteractPayload,\n PlaygroundInteractResult,\n PlaygroundPageRecordedEvent,\n} from './sdk/index';\nexport type {\n BeforeActionHook,\n ExecutionOptions,\n FormValue,\n PlaygroundAgent,\n ValidationResult,\n PlaygroundConfig,\n ExecutionType,\n PlaygroundAdapter,\n} from './types';\nexport type {\n PlaygroundCreatedSession,\n PlaygroundExecutionHooks,\n PlaygroundPlatformRegistration,\n PlaygroundPlatformDescriptor,\n PlaygroundPlatformSelectorConfig,\n PlaygroundPreviewCapability,\n PlaygroundPreviewDescriptor,\n PlaygroundPreviewKind,\n PlaygroundRecorderCapabilitiesResult,\n PlaygroundRecorderDescribeResult,\n PlaygroundRecorderEvent,\n PlaygroundRecorderEventsResult,\n PlaygroundRecorderSourceKind,\n PlaygroundRecorderStartResult,\n PlaygroundSidecar,\n PreparedPlaygroundPlatform,\n PlaygroundSessionField,\n PlaygroundSessionFieldOption,\n PlaygroundSessionManager,\n PlaygroundSessionSetup,\n PlaygroundSessionState,\n PlaygroundSessionTarget,\n} from './platform';\nexport type { PlaygroundRuntimeInfo } from './runtime-metadata';\n"],"names":["PlaygroundServer","undefined","playgroundForAgent","playgroundForAgentFactory","playgroundForSessionManager","launchPreparedPlaygroundPlatform"],"mappings":";;;;;;AAwBO,MAAMA,mBAAmBC;AACzB,MAAMC,qBAAqBD;AAC3B,MAAME,4BAA4BF;AAClC,MAAMG,8BAA8BH;AACpC,MAAMI,mCAAmCJ"}
@@ -40,6 +40,9 @@ class InterfaceMjpegHub {
40
40
  producer.responses.clear();
41
41
  this.stopProducerInternal(producer);
42
42
  }
43
+ getLastFrame() {
44
+ return this.producer?.lastFrame;
45
+ }
43
46
  async streamRequestInternal(req, res, activeInterface, recoverActiveAgent, allowRecovery) {
44
47
  const producer = this.getOrCreateProducer(activeInterface);
45
48
  if (!producer) return false;