@midscene/playground 1.0.1-beta-20251216072405.0 → 1.0.1-beta-20251216140107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/adapters/local-execution.mjs.map +1 -1
- package/dist/lib/adapters/local-execution.js.map +1 -1
- package/package.json +3 -3
- package/static/index.html +1 -1
- package/static/static/js/{index.02c6cb9f.js → index.16e50581.js} +5 -5
- package/static/static/js/index.16e50581.js.map +1 -0
- package/static/static/js/index.02c6cb9f.js.map +0 -1
- /package/static/static/js/{index.02c6cb9f.js.LICENSE.txt → index.16e50581.js.LICENSE.txt} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters/local-execution.mjs","sources":["../../../src/adapters/local-execution.ts"],"sourcesContent":["import type { DeviceAction, ExecutionDump } from '@midscene/core';\nimport { overrideAIConfig } from '@midscene/shared/env';\nimport { uuid } from '@midscene/shared/utils';\nimport { executeAction, parseStructuredParams } from '../common';\nimport type { ExecutionOptions, FormValue, PlaygroundAgent } from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class LocalExecutionAdapter extends BasePlaygroundAdapter {\n private agent: PlaygroundAgent;\n private dumpUpdateCallback?: (\n dump: string,\n executionDump?: ExecutionDump,\n ) => 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) {\n super();\n this.agent = agent;\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 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 // 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 }\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 // 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 this.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 && this.agent) {\n // Track current request ID to prevent stale callbacks\n this.currentRequestId = options.requestId;\n\n // Add listener and save remove function\n removeListener = this.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 this.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 try {\n if (this.agent.dumpDataString) {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n const groupedDump = JSON.parse(dumpString);\n response.dump = groupedDump.executions?.[0] || null;\n }\n }\n\n if (this.agent.reportHTMLString) {\n response.reportHTML = this.agent.reportHTMLString() || null;\n }\n\n // Write out action dumps\n if (this.agent.writeOutActionDumps) {\n this.agent.writeOutActionDumps();\n }\n } catch (error: unknown) {\n console.error('Failed to get dump/reportHTML from agent:', error);\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 // Local execution task cancellation - minimal implementation\n async cancelTask(\n _requestId: string,\n ): Promise<{ error?: string; success?: boolean }> {\n if (!this.agent) {\n return { error: 'No active agent found for this requestId' };\n }\n\n try {\n await this.agent.destroy?.();\n return { success: true };\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to cancel agent: ${errorMessage}`);\n return { error: `Failed to cancel: ${errorMessage}` };\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 = JSON.parse(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 } | 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\n return {\n type,\n description,\n };\n } catch (error: unknown) {\n console.error('Failed to get interface info:', error);\n return null;\n }\n }\n}\n"],"names":["LocalExecutionAdapter","BasePlaygroundAdapter","callback","undefined","action","params","options","parseStructuredParams","error","errorMessage","context","page","contextPage","aiConfig","overrideAIConfig","console","actionType","value","actionSpace","removeListener","dump","executionDump","result","executionError","executeAction","response","Error","String","dumpString","groupedDump","JSON","_requestId","type","description","agent","uuid"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapters/local-execution.mjs","sources":["../../../src/adapters/local-execution.ts"],"sourcesContent":["import type { DeviceAction, ExecutionDump } from '@midscene/core';\nimport { overrideAIConfig } from '@midscene/shared/env';\nimport { uuid } from '@midscene/shared/utils';\nimport { executeAction, parseStructuredParams } from '../common';\nimport type { ExecutionOptions, FormValue, PlaygroundAgent } from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class LocalExecutionAdapter extends BasePlaygroundAdapter {\n private agent: PlaygroundAgent;\n private dumpUpdateCallback?: (\n dump: string,\n executionDump?: ExecutionDump,\n ) => 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) {\n super();\n this.agent = agent;\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 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 // 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 }\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 // 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 this.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 && this.agent) {\n // Track current request ID to prevent stale callbacks\n this.currentRequestId = options.requestId;\n\n // Add listener and save remove function\n removeListener = this.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 this.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 try {\n if (this.agent.dumpDataString) {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n const groupedDump = JSON.parse(dumpString);\n response.dump = groupedDump.executions?.[0] || null;\n }\n }\n\n // Always generate reportHTML for all APIs (including noReplayAPIs)\n if (this.agent.reportHTMLString) {\n response.reportHTML = this.agent.reportHTMLString() || null;\n }\n\n // Write out action dumps\n if (this.agent.writeOutActionDumps) {\n this.agent.writeOutActionDumps();\n }\n } catch (error: unknown) {\n console.error('Failed to get dump/reportHTML from agent:', error);\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 // Local execution task cancellation - minimal implementation\n async cancelTask(\n _requestId: string,\n ): Promise<{ error?: string; success?: boolean }> {\n if (!this.agent) {\n return { error: 'No active agent found for this requestId' };\n }\n\n try {\n await this.agent.destroy?.();\n return { success: true };\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to cancel agent: ${errorMessage}`);\n return { error: `Failed to cancel: ${errorMessage}` };\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 = JSON.parse(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 } | 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\n return {\n type,\n description,\n };\n } catch (error: unknown) {\n console.error('Failed to get interface info:', error);\n return null;\n }\n }\n}\n"],"names":["LocalExecutionAdapter","BasePlaygroundAdapter","callback","undefined","action","params","options","parseStructuredParams","error","errorMessage","context","page","contextPage","aiConfig","overrideAIConfig","console","actionType","value","actionSpace","removeListener","dump","executionDump","result","executionError","executeAction","response","Error","String","dumpString","groupedDump","JSON","_requestId","type","description","agent","uuid"],"mappings":";;;;;;;;;;;;;;AAOO,MAAMA,8BAA8BC;IAgBzC,IAAI,KAAa;QACf,OAAO,IAAI,CAAC,GAAG;IACjB;IAEA,aACEC,QAA+D,EACzD;QAEN,IAAI,CAAC,kBAAkB,GAAGC;QAE1B,IAAI,CAAC,kBAAkB,GAAGD;IAC5B;IAEA,MAAM,sBACJE,MAA6B,EAC7BC,MAA+B,EAC/BC,OAAyB,EACL;QAEpB,OAAO,MAAMC,sBAAsBH,QAAQC,QAAQC;IACrD;IAEA,mBAAmBE,KAAU,EAAU;QACrC,MAAMC,eAAeD,OAAO,WAAW;QACvC,IAAIC,aAAa,QAAQ,CAAC,2BACxB,OAAO;QAET,OAAO,IAAI,CAAC,uBAAuB,CAACD;IACtC;IAMA,MAAM,eAAeE,OAAiB,EAAoC;QAExE,IAAI,IAAI,CAAC,KAAK,EAAE,gBACd,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc;QAIxC,IACE,IAAI,CAAC,KAAK,IACV,eAAe,IAAI,CAAC,KAAK,IACzB,AAAgC,YAAhC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,EAC3B;YACA,MAAMC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS;YAGjC,IAAIA,MAAM,aACR,OAAOA,KAAK,WAAW;QAE3B;QAGA,IAAID,WAAW,AAAmB,YAAnB,OAAOA,WAAwB,iBAAiBA,SAAS;YACtE,MAAME,cAAcF;YAGpB,OAAOE,YAAY,WAAW;QAChC;QAEA,OAAO,EAAE;IACX;IAGA,MAAM,cAAgC;QACpC,OAAO;IACT;IAEA,MAAM,eAAeC,QAAiC,EAAiB;QAErEC,iBAAiBD;IACnB;IAQA,MAAc,uBAAuB;QACnC,IAAI;YACF,MAAMF,OAAO,IAAI,CAAC,KAAK,EAAE;YAGzB,MAAMA,MAAM;QACd,EAAE,OAAOH,OAAO;YACdO,QAAQ,IAAI,CAAC,8BAA8BP;QAC7C;IACF;IAEA,MAAM,cACJQ,UAAkB,EAClBC,KAAgB,EAChBX,OAAyB,EACP;QAElB,MAAMY,cAAc,MAAM,IAAI,CAAC,cAAc;QAC7C,IAAIC;QAGJ,IAAI;YACF,IAAI,CAAC,KAAK,CAAC,SAAS;QACtB,EAAE,OAAOX,OAAgB;YACvBO,QAAQ,IAAI,CAAC,0CAA0CP;QACzD;QAGA,IAAIF,QAAQ,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE;YAEnC,IAAI,CAAC,gBAAgB,GAAGA,QAAQ,SAAS;YAGzCa,iBAAiB,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAC/C,CAACC,MAAcC;gBAEb,IAAI,IAAI,CAAC,gBAAgB,KAAKf,QAAQ,SAAS,EAC7C;gBAIF,IAAI,IAAI,CAAC,kBAAkB,EACzB,IAAI,CAAC,kBAAkB,CAACc,MAAMC;YAElC;QAEJ;QAEA,IAAI;YACF,IAAIC,SAAS;YACb,IAAIC,iBAAiB;YAErB,IAAI;gBAEFD,SAAS,MAAME,cACb,IAAI,CAAC,KAAK,EACVR,YACAE,aACAD,OACAX;YAEJ,EAAE,OAAOE,OAAgB;gBAEvBe,iBAAiBf;YACnB;YAGA,MAAMiB,WAAW;gBACfH;gBACA,MAAM;gBACN,YAAY;gBACZ,OAAOC,iBACHA,0BAA0BG,QACxBH,eAAe,OAAO,GACtBI,OAAOJ,kBACT;YACN;YAEA,IAAI;gBACF,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;oBAC7B,MAAMK,aAAa,IAAI,CAAC,KAAK,CAAC,cAAc;oBAC5C,IAAIA,YAAY;wBACd,MAAMC,cAAcC,KAAK,KAAK,CAACF;wBAC/BH,SAAS,IAAI,GAAGI,YAAY,UAAU,EAAE,CAAC,EAAE,IAAI;oBACjD;gBACF;gBAGA,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAC7BJ,SAAS,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,MAAM;gBAIzD,IAAI,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAChC,IAAI,CAAC,KAAK,CAAC,mBAAmB;YAElC,EAAE,OAAOjB,OAAgB;gBACvBO,QAAQ,KAAK,CAAC,6CAA6CP;YAC7D;YAIA,OAAOiB;QACT,SAAU;YAER,IAAIN,gBACFA;QAEJ;IACF;IAGA,MAAM,WACJY,UAAkB,EAC8B;QAChD,IAAI,CAAC,IAAI,CAAC,KAAK,EACb,OAAO;YAAE,OAAO;QAA2C;QAG7D,IAAI;YACF,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO;YACxB,OAAO;gBAAE,SAAS;YAAK;QACzB,EAAE,OAAOvB,OAAgB;YACvB,MAAMC,eACJD,iBAAiBkB,QAAQlB,MAAM,OAAO,GAAG;YAC3CO,QAAQ,KAAK,CAAC,CAAC,wBAAwB,EAAEN,cAAc;YACvD,OAAO;gBAAE,OAAO,CAAC,kBAAkB,EAAEA,cAAc;YAAC;QACtD;IACF;IAMA,MAAM,0BAGH;QACD,MAAMgB,WAAW;YACf,MAAM;YACN,YAAY;QACd;QAEA,IAAI;YAEF,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;gBAC7B,MAAMG,aAAa,IAAI,CAAC,KAAK,CAAC,cAAc;gBAC5C,IAAIA,YAAY;oBACd,MAAMC,cAAcC,KAAK,KAAK,CAACF;oBAC/BH,SAAS,IAAI,GAAGI,YAAY,UAAU,EAAE,CAAC,EAAE,IAAI;gBACjD;YACF;YAGA,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAC7BJ,SAAS,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,MAAM;QAE3D,EAAE,OAAOjB,OAAgB;YACvBO,QAAQ,KAAK,CAAC,yCAAyCP;QACzD;QAEA,OAAOiB;IACT;IAGA,MAAM,mBAGI;QACR,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,WACf,OAAO;QAGT,IAAI;YACF,MAAMO,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,aAAa,IAAI;YACnD,MAAMC,cAAc,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,QAAQ9B;YAEzD,OAAO;gBACL6B;gBACAC;YACF;QACF,EAAE,OAAOzB,OAAgB;YACvBO,QAAQ,KAAK,CAAC,iCAAiCP;YAC/C,OAAO;QACT;IACF;IAjRA,YAAY0B,KAAsB,CAAE;QAClC,KAAK,IATP,uBAAQ,SAAR,SACA,uBAAQ,sBAAR,SAIA,uBAAiB,OAAjB,SACA,uBAAQ,oBAAR;QAIE,IAAI,CAAC,KAAK,GAAGA;QACb,IAAI,CAAC,GAAG,GAAGC;IACb;AA8QF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters/local-execution.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/adapters/local-execution.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { DeviceAction, ExecutionDump } from '@midscene/core';\nimport { overrideAIConfig } from '@midscene/shared/env';\nimport { uuid } from '@midscene/shared/utils';\nimport { executeAction, parseStructuredParams } from '../common';\nimport type { ExecutionOptions, FormValue, PlaygroundAgent } from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class LocalExecutionAdapter extends BasePlaygroundAdapter {\n private agent: PlaygroundAgent;\n private dumpUpdateCallback?: (\n dump: string,\n executionDump?: ExecutionDump,\n ) => 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) {\n super();\n this.agent = agent;\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 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 // 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 }\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 // 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 this.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 && this.agent) {\n // Track current request ID to prevent stale callbacks\n this.currentRequestId = options.requestId;\n\n // Add listener and save remove function\n removeListener = this.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 this.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 try {\n if (this.agent.dumpDataString) {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n const groupedDump = JSON.parse(dumpString);\n response.dump = groupedDump.executions?.[0] || null;\n }\n }\n\n if (this.agent.reportHTMLString) {\n response.reportHTML = this.agent.reportHTMLString() || null;\n }\n\n // Write out action dumps\n if (this.agent.writeOutActionDumps) {\n this.agent.writeOutActionDumps();\n }\n } catch (error: unknown) {\n console.error('Failed to get dump/reportHTML from agent:', error);\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 // Local execution task cancellation - minimal implementation\n async cancelTask(\n _requestId: string,\n ): Promise<{ error?: string; success?: boolean }> {\n if (!this.agent) {\n return { error: 'No active agent found for this requestId' };\n }\n\n try {\n await this.agent.destroy?.();\n return { success: true };\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to cancel agent: ${errorMessage}`);\n return { error: `Failed to cancel: ${errorMessage}` };\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 = JSON.parse(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 } | 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\n return {\n type,\n description,\n };\n } catch (error: unknown) {\n console.error('Failed to get interface info:', error);\n return null;\n }\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","LocalExecutionAdapter","BasePlaygroundAdapter","callback","undefined","action","params","options","parseStructuredParams","error","errorMessage","context","page","contextPage","aiConfig","overrideAIConfig","console","actionType","value","actionSpace","removeListener","dump","executionDump","result","executionError","executeAction","response","Error","String","dumpString","groupedDump","JSON","_requestId","type","description","agent","uuid"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapters/local-execution.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/adapters/local-execution.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { DeviceAction, ExecutionDump } from '@midscene/core';\nimport { overrideAIConfig } from '@midscene/shared/env';\nimport { uuid } from '@midscene/shared/utils';\nimport { executeAction, parseStructuredParams } from '../common';\nimport type { ExecutionOptions, FormValue, PlaygroundAgent } from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class LocalExecutionAdapter extends BasePlaygroundAdapter {\n private agent: PlaygroundAgent;\n private dumpUpdateCallback?: (\n dump: string,\n executionDump?: ExecutionDump,\n ) => 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) {\n super();\n this.agent = agent;\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 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 // 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 }\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 // 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 this.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 && this.agent) {\n // Track current request ID to prevent stale callbacks\n this.currentRequestId = options.requestId;\n\n // Add listener and save remove function\n removeListener = this.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 this.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 try {\n if (this.agent.dumpDataString) {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n const groupedDump = JSON.parse(dumpString);\n response.dump = groupedDump.executions?.[0] || null;\n }\n }\n\n // Always generate reportHTML for all APIs (including noReplayAPIs)\n if (this.agent.reportHTMLString) {\n response.reportHTML = this.agent.reportHTMLString() || null;\n }\n\n // Write out action dumps\n if (this.agent.writeOutActionDumps) {\n this.agent.writeOutActionDumps();\n }\n } catch (error: unknown) {\n console.error('Failed to get dump/reportHTML from agent:', error);\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 // Local execution task cancellation - minimal implementation\n async cancelTask(\n _requestId: string,\n ): Promise<{ error?: string; success?: boolean }> {\n if (!this.agent) {\n return { error: 'No active agent found for this requestId' };\n }\n\n try {\n await this.agent.destroy?.();\n return { success: true };\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to cancel agent: ${errorMessage}`);\n return { error: `Failed to cancel: ${errorMessage}` };\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 = JSON.parse(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 } | 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\n return {\n type,\n description,\n };\n } catch (error: unknown) {\n console.error('Failed to get interface info:', error);\n return null;\n }\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","LocalExecutionAdapter","BasePlaygroundAdapter","callback","undefined","action","params","options","parseStructuredParams","error","errorMessage","context","page","contextPage","aiConfig","overrideAIConfig","console","actionType","value","actionSpace","removeListener","dump","executionDump","result","executionError","executeAction","response","Error","String","dumpString","groupedDump","JSON","_requestId","type","description","agent","uuid"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midscene/playground",
|
|
3
|
-
"version": "1.0.1-beta-
|
|
3
|
+
"version": "1.0.1-beta-20251216140107.0",
|
|
4
4
|
"description": "Midscene playground utilities for web integration",
|
|
5
5
|
"author": "midscene team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"express": "^4.21.2",
|
|
26
26
|
"open": "10.1.0",
|
|
27
27
|
"uuid": "11.1.0",
|
|
28
|
-
"@midscene/core": "1.0.1-beta-
|
|
29
|
-
"@midscene/shared": "1.0.1-beta-
|
|
28
|
+
"@midscene/core": "1.0.1-beta-20251216140107.0",
|
|
29
|
+
"@midscene/shared": "1.0.1-beta-20251216140107.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@rslib/core": "^0.18.3",
|
package/static/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html><head><link rel="icon" href="/favicon.ico"><title>Midscene Playground</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script defer src="/static/js/lib-react.bc3a3965.js"></script><script defer src="/static/js/430.adc9a336.js"></script><script defer src="/static/js/index.
|
|
1
|
+
<!doctype html><html><head><link rel="icon" href="/favicon.ico"><title>Midscene Playground</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script defer src="/static/js/lib-react.bc3a3965.js"></script><script defer src="/static/js/430.adc9a336.js"></script><script defer src="/static/js/index.16e50581.js"></script><link href="/static/css/index.f072998e.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
|