@sqaitech/playground 0.5.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/base.mjs +131 -0
- package/dist/es/adapters/base.mjs.map +1 -0
- package/dist/es/adapters/local-execution.mjs +140 -0
- package/dist/es/adapters/local-execution.mjs.map +1 -0
- package/dist/es/adapters/remote-execution.mjs +308 -0
- package/dist/es/adapters/remote-execution.mjs.map +1 -0
- package/dist/es/common.mjs +148 -0
- package/dist/es/common.mjs.map +1 -0
- package/dist/es/index.browser.mjs +9 -0
- package/dist/es/index.browser.mjs.map +1 -0
- package/dist/es/index.mjs +8 -0
- package/dist/es/launcher.mjs +95 -0
- package/dist/es/launcher.mjs.map +1 -0
- package/dist/es/sdk/index.mjs +102 -0
- package/dist/es/sdk/index.mjs.map +1 -0
- package/dist/es/server.mjs +385 -0
- package/dist/es/server.mjs.map +1 -0
- package/dist/es/types.mjs +0 -0
- package/dist/lib/adapters/base.js +165 -0
- package/dist/lib/adapters/base.js.map +1 -0
- package/dist/lib/adapters/local-execution.js +174 -0
- package/dist/lib/adapters/local-execution.js.map +1 -0
- package/dist/lib/adapters/remote-execution.js +342 -0
- package/dist/lib/adapters/remote-execution.js.map +1 -0
- package/dist/lib/common.js +200 -0
- package/dist/lib/common.js.map +1 -0
- package/dist/lib/index.browser.js +73 -0
- package/dist/lib/index.browser.js.map +1 -0
- package/dist/lib/index.js +77 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/launcher.js +140 -0
- package/dist/lib/launcher.js.map +1 -0
- package/dist/lib/sdk/index.js +136 -0
- package/dist/lib/sdk/index.js.map +1 -0
- package/dist/lib/server.js +435 -0
- package/dist/lib/server.js.map +1 -0
- package/dist/lib/types.js +20 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/types/adapters/base.d.ts +20 -0
- package/dist/types/adapters/local-execution.d.ts +31 -0
- package/dist/types/adapters/remote-execution.d.ts +38 -0
- package/dist/types/common.d.ts +9 -0
- package/dist/types/index.browser.d.ts +7 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/launcher.d.ts +97 -0
- package/dist/types/sdk/index.d.ts +31 -0
- package/dist/types/server.d.ts +75 -0
- package/dist/types/types.d.ts +49 -0
- package/package.json +51 -0
- package/static/favicon.ico +0 -0
- package/static/index.html +1 -0
- package/static/static/css/index.60c69390.css +2 -0
- package/static/static/css/index.60c69390.css.map +1 -0
- package/static/static/image/sqai-logo.b7f781cd.png +0 -0
- package/static/static/js/931.dc961e99.js +620 -0
- package/static/static/js/931.dc961e99.js.LICENSE.txt +146 -0
- package/static/static/js/931.dc961e99.js.map +1 -0
- package/static/static/js/async/173.9cf6b074.js +3 -0
- package/static/static/js/async/173.9cf6b074.js.map +1 -0
- package/static/static/js/async/212.e243c338.js +158 -0
- package/static/static/js/async/212.e243c338.js.map +1 -0
- package/static/static/js/async/329.f888b505.js +26 -0
- package/static/static/js/async/329.f888b505.js.map +1 -0
- package/static/static/js/async/364.1821e74b.js +30 -0
- package/static/static/js/async/364.1821e74b.js.map +1 -0
- package/static/static/js/async/544.b73fa603.js +2 -0
- package/static/static/js/async/544.b73fa603.js.map +1 -0
- package/static/static/js/async/582.5dccae2d.js +21 -0
- package/static/static/js/async/582.5dccae2d.js.map +1 -0
- package/static/static/js/async/624.45ee2b2c.js +3 -0
- package/static/static/js/async/624.45ee2b2c.js.map +1 -0
- package/static/static/js/async/644.6bdc4065.js +1 -0
- package/static/static/js/async/659.9afd03db.js +21 -0
- package/static/static/js/async/659.9afd03db.js.map +1 -0
- package/static/static/js/async/702.60261735.js +231 -0
- package/static/static/js/async/702.60261735.js.map +1 -0
- package/static/static/js/async/920.7d9a9aa8.js +2 -0
- package/static/static/js/async/920.7d9a9aa8.js.map +1 -0
- package/static/static/js/async/983.8b91303f.js +1 -0
- package/static/static/js/index.0c5d4f3b.js +10 -0
- package/static/static/js/index.0c5d4f3b.js.LICENSE.txt +7 -0
- package/static/static/js/index.0c5d4f3b.js.map +1 -0
- package/static/static/js/index.3890f2de.js +10 -0
- package/static/static/js/index.3890f2de.js.LICENSE.txt +7 -0
- package/static/static/js/index.3890f2de.js.map +1 -0
- package/static/static/js/index.39b0d1ea.js +10 -0
- package/static/static/js/index.39b0d1ea.js.LICENSE.txt +7 -0
- package/static/static/js/index.39b0d1ea.js.map +1 -0
- package/static/static/js/index.3f24d218.js +10 -0
- package/static/static/js/index.3f24d218.js.LICENSE.txt +7 -0
- package/static/static/js/index.3f24d218.js.map +1 -0
- package/static/static/js/index.5cccbdaf.js +10 -0
- package/static/static/js/index.5cccbdaf.js.LICENSE.txt +7 -0
- package/static/static/js/index.5cccbdaf.js.map +1 -0
- package/static/static/js/index.8a10896b.js +10 -0
- package/static/static/js/index.8a10896b.js.LICENSE.txt +7 -0
- package/static/static/js/index.8a10896b.js.map +1 -0
- package/static/static/js/index.afc8ef37.js +10 -0
- package/static/static/js/index.afc8ef37.js.LICENSE.txt +7 -0
- package/static/static/js/index.afc8ef37.js.map +1 -0
- package/static/static/js/index.b8a17a87.js +10 -0
- package/static/static/js/index.b8a17a87.js.LICENSE.txt +7 -0
- package/static/static/js/index.b8a17a87.js.map +1 -0
- package/static/static/js/index.d0dcab60.js +10 -0
- package/static/static/js/index.d0dcab60.js.LICENSE.txt +7 -0
- package/static/static/js/index.d0dcab60.js.map +1 -0
- package/static/static/js/index.f21bb1df.js +10 -0
- package/static/static/js/index.f21bb1df.js.LICENSE.txt +7 -0
- package/static/static/js/index.f21bb1df.js.map +1 -0
- package/static/static/js/lib-react.f566a9ed.js +3 -0
- package/static/static/js/lib-react.f566a9ed.js.LICENSE.txt +39 -0
- package/static/static/js/lib-react.f566a9ed.js.map +1 -0
- package/static/static/svg/server-offline-foreground.3113df3c.svg +36 -0
- package/static/static/wasm/9e906fbf55e08f98.module.wasm +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters\\remote-execution.mjs","sources":["webpack://@sqaitech/playground/./src/adapters/remote-execution.ts"],"sourcesContent":["import type { DeviceAction } from '@sqaitech/core';\r\nimport { parseStructuredParams } from '../common';\r\nimport type { ExecutionOptions, FormValue, ValidationResult } from '../types';\r\nimport { BasePlaygroundAdapter } from './base';\r\n\r\nexport class RemoteExecutionAdapter extends BasePlaygroundAdapter {\r\n private serverUrl?: string;\r\n private progressPolling = new Map<string, NodeJS.Timeout>();\r\n private progressCallback?: (tip: string) => void;\r\n private _id?: string;\r\n\r\n constructor(serverUrl: string) {\r\n super();\r\n this.serverUrl = serverUrl;\r\n }\r\n\r\n // Get adapter ID (cached after first status check for remote)\r\n get id(): string | undefined {\r\n return this._id;\r\n }\r\n\r\n // Override validateParams for remote execution\r\n // Since schemas from server are JSON-serialized and lack .parse() method\r\n validateParams(\r\n value: FormValue,\r\n action: DeviceAction<unknown> | undefined,\r\n ): ValidationResult {\r\n if (!action?.paramSchema) {\r\n return { valid: true };\r\n }\r\n\r\n const needsStructuredParams = this.actionNeedsStructuredParams(action);\r\n\r\n if (!needsStructuredParams) {\r\n return { valid: true };\r\n }\r\n\r\n if (!value.params) {\r\n return { valid: false, errorMessage: 'Parameters are required' };\r\n }\r\n\r\n // For remote execution, perform basic validation without .parse()\r\n // Check if required fields are present\r\n if (action.paramSchema && typeof action.paramSchema === 'object') {\r\n const schema = action.paramSchema as any;\r\n if (schema.shape || schema.type === 'ZodObject') {\r\n const shape = schema.shape || {};\r\n const missingFields = Object.keys(shape).filter((key) => {\r\n const fieldDef = shape[key];\r\n // Check if field is required (not optional)\r\n const isOptional =\r\n fieldDef?.isOptional ||\r\n fieldDef?._def?.innerType || // ZodOptional\r\n fieldDef?._def?.typeName === 'ZodOptional';\r\n return (\r\n !isOptional &&\r\n (value.params![key] === undefined || value.params![key] === '')\r\n );\r\n });\r\n\r\n if (missingFields.length > 0) {\r\n return {\r\n valid: false,\r\n errorMessage: `Missing required parameters: ${missingFields.join(', ')}`,\r\n };\r\n }\r\n }\r\n }\r\n\r\n return { valid: true };\r\n }\r\n\r\n async parseStructuredParams(\r\n action: DeviceAction<unknown>,\r\n params: Record<string, unknown>,\r\n options: ExecutionOptions,\r\n ): Promise<unknown[]> {\r\n // Use shared implementation from common.ts\r\n return await parseStructuredParams(action, params, options);\r\n }\r\n\r\n formatErrorMessage(error: any): string {\r\n const message = error?.message || '';\r\n\r\n // Handle Android-specific errors\r\n const androidErrors = [\r\n {\r\n keyword: 'adb',\r\n message:\r\n 'ADB connection error. Please ensure device is connected and USB debugging is enabled.',\r\n },\r\n {\r\n keyword: 'UIAutomator',\r\n message:\r\n 'UIAutomator error. Please ensure the UIAutomator server is running on the device.',\r\n },\r\n ];\r\n\r\n const androidError = androidErrors.find(({ keyword }) =>\r\n message.includes(keyword),\r\n );\r\n if (androidError) {\r\n return androidError.message;\r\n }\r\n\r\n return this.formatBasicErrorMessage(error);\r\n }\r\n\r\n // Remote execution adapter - simplified interface\r\n async executeAction(\r\n actionType: string,\r\n value: FormValue,\r\n options: ExecutionOptions,\r\n ): Promise<unknown> {\r\n // If serverUrl is provided, use server-side execution\r\n if (this.serverUrl && typeof window !== 'undefined') {\r\n return this.executeViaServer(actionType, value, options);\r\n }\r\n\r\n throw new Error(\r\n 'Remote execution adapter requires server URL for execution',\r\n );\r\n }\r\n\r\n // Remote execution via server - uses same endpoint as requestPlaygroundServer\r\n private async executeViaServer(\r\n actionType: string,\r\n value: FormValue,\r\n options: ExecutionOptions,\r\n ): Promise<unknown> {\r\n const payload: Record<string, unknown> = {\r\n type: actionType,\r\n prompt: value.prompt,\r\n ...this.buildOptionalPayloadParams(options, value),\r\n };\r\n\r\n // Add context only if it exists (server can handle single agent case without context)\r\n if (options.context) {\r\n payload.context = options.context;\r\n }\r\n\r\n // Start progress polling if callback is set and requestId exists\r\n if (options.requestId && this.progressCallback) {\r\n this.startProgressPolling(options.requestId, this.progressCallback);\r\n }\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/execute`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(payload),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(\r\n `Server request failed (${response.status}): ${errorText}`,\r\n );\r\n }\r\n\r\n const result = await response.json();\r\n\r\n // Stop progress polling when execution completes\r\n if (options.requestId) {\r\n this.stopProgressPolling(options.requestId);\r\n }\r\n\r\n return result;\r\n } catch (error) {\r\n // Stop progress polling on error\r\n if (options.requestId) {\r\n this.stopProgressPolling(options.requestId);\r\n }\r\n console.error('Execute via server failed:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n // Helper method to build optional payload parameters\r\n private buildOptionalPayloadParams(\r\n options: ExecutionOptions,\r\n value: FormValue,\r\n ): Record<string, unknown> {\r\n const optionalParams: Record<string, unknown> = {};\r\n\r\n // Add optional parameters only if they have meaningful values\r\n const optionalFields = [\r\n { key: 'requestId', value: options.requestId },\r\n { key: 'deepThink', value: options.deepThink },\r\n { key: 'screenshotIncluded', value: options.screenshotIncluded },\r\n { key: 'domIncluded', value: options.domIncluded },\r\n { key: 'params', value: value.params },\r\n ] as const;\r\n\r\n optionalFields.forEach(({ key, value }) => {\r\n if (value !== undefined && value !== null && value !== '') {\r\n optionalParams[key] = value;\r\n }\r\n });\r\n\r\n return optionalParams;\r\n }\r\n\r\n // Get action space from server with fallback\r\n async getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]> {\r\n // Try server first if available\r\n if (this.serverUrl && typeof window !== 'undefined') {\r\n try {\r\n const response = await fetch(`${this.serverUrl}/action-space`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({ context }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to get action space: ${response.statusText}`);\r\n }\r\n\r\n const result = await response.json();\r\n return Array.isArray(result) ? result : [];\r\n } catch (error) {\r\n console.error('Failed to get action space from server:', error);\r\n // Fall through to context fallback\r\n }\r\n }\r\n\r\n // Fallback: try context.actionSpace if available\r\n if (context && typeof context === 'object' && 'actionSpace' in context) {\r\n try {\r\n const actionSpaceMethod = (\r\n context as { actionSpace: () => Promise<DeviceAction<unknown>[]> }\r\n ).actionSpace;\r\n const result = await actionSpaceMethod();\r\n return Array.isArray(result) ? result : [];\r\n } catch (error) {\r\n console.error('Failed to get action space from context:', error);\r\n }\r\n }\r\n\r\n return [];\r\n }\r\n\r\n // Uses base implementation for validateParams and createDisplayContent\r\n\r\n // Server communication methods\r\n async checkStatus(): Promise<boolean> {\r\n if (!this.serverUrl) {\r\n return false;\r\n }\r\n\r\n try {\r\n const res = await fetch(`${this.serverUrl}/status`);\r\n if (res.status === 200) {\r\n // Try to extract id from response\r\n try {\r\n const data = await res.json();\r\n if (data.id && typeof data.id === 'string') {\r\n this._id = data.id;\r\n }\r\n } catch (jsonError) {\r\n // If JSON parsing fails, id remains undefined but status is still OK\r\n console.debug('Failed to parse status response:', jsonError);\r\n }\r\n return true;\r\n }\r\n return false;\r\n } catch (error) {\r\n console.warn('Server status check failed:', error);\r\n return false;\r\n }\r\n }\r\n\r\n async overrideConfig(aiConfig: Record<string, unknown>): Promise<void> {\r\n if (!this.serverUrl) {\r\n throw new Error('Server URL not configured');\r\n }\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/config`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({ aiConfig }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(\r\n `Failed to override server config: ${response.statusText}`,\r\n );\r\n }\r\n } catch (error) {\r\n console.error('Failed to override server config:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n async getTaskProgress(requestId: string): Promise<{ tip?: string }> {\r\n if (!this.serverUrl) {\r\n return { tip: undefined };\r\n }\r\n\r\n if (!requestId?.trim()) {\r\n console.warn('Invalid requestId provided for task progress');\r\n return { tip: undefined };\r\n }\r\n\r\n try {\r\n const response = await fetch(\r\n `${this.serverUrl}/task-progress/${encodeURIComponent(requestId)}`,\r\n );\r\n\r\n if (!response.ok) {\r\n console.warn(`Task progress request failed: ${response.statusText}`);\r\n return { tip: undefined };\r\n }\r\n\r\n return await response.json();\r\n } catch (error) {\r\n console.error('Failed to poll task progress:', error);\r\n return { tip: undefined };\r\n }\r\n }\r\n\r\n // Cancel task\r\n async cancelTask(\r\n requestId: string,\r\n ): Promise<{ error?: string; success?: boolean }> {\r\n // Stop progress polling\r\n this.stopProgressPolling(requestId);\r\n\r\n if (!this.serverUrl) {\r\n return { error: 'No server URL configured' };\r\n }\r\n\r\n if (!requestId?.trim()) {\r\n return { error: 'Invalid request ID' };\r\n }\r\n\r\n try {\r\n const res = await fetch(\r\n `${this.serverUrl}/cancel/${encodeURIComponent(requestId)}`,\r\n {\r\n method: 'POST',\r\n },\r\n );\r\n\r\n if (!res.ok) {\r\n return { error: `Cancel request failed: ${res.statusText}` };\r\n }\r\n\r\n const result = await res.json();\r\n return { success: true, ...result };\r\n } catch (error) {\r\n console.error('Failed to cancel task:', error);\r\n return { error: 'Failed to cancel task' };\r\n }\r\n }\r\n\r\n // Progress callback management\r\n setProgressCallback(callback: (tip: string) => void): void {\r\n this.progressCallback = callback;\r\n }\r\n\r\n // Start progress polling\r\n private startProgressPolling(\r\n requestId: string,\r\n callback: (tip: string) => void,\r\n ): void {\r\n // Don't start multiple polling for the same request\r\n if (this.progressPolling.has(requestId)) {\r\n return;\r\n }\r\n\r\n let lastTip = '';\r\n const interval = setInterval(async () => {\r\n try {\r\n const progress = await this.getTaskProgress(requestId);\r\n if (progress?.tip?.trim?.() && progress.tip !== lastTip) {\r\n lastTip = progress.tip;\r\n callback(progress.tip);\r\n }\r\n } catch (error) {\r\n // Silently ignore progress polling errors to avoid spam\r\n console.debug('Progress polling error:', error);\r\n }\r\n }, 500); // Poll every 500ms\r\n\r\n this.progressPolling.set(requestId, interval);\r\n }\r\n\r\n // Stop progress polling\r\n private stopProgressPolling(requestId: string): void {\r\n const interval = this.progressPolling.get(requestId);\r\n if (interval) {\r\n clearInterval(interval);\r\n this.progressPolling.delete(requestId);\r\n }\r\n }\r\n\r\n // Get screenshot from server\r\n async getScreenshot(): Promise<{\r\n screenshot: string;\r\n timestamp: number;\r\n } | null> {\r\n if (!this.serverUrl) {\r\n return null;\r\n }\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/screenshot`);\r\n\r\n if (!response.ok) {\r\n console.warn(`Screenshot request failed: ${response.statusText}`);\r\n return null;\r\n }\r\n\r\n return await response.json();\r\n } catch (error) {\r\n console.error('Failed to get screenshot:', error);\r\n return null;\r\n }\r\n }\r\n\r\n // Get interface information from server\r\n async getInterfaceInfo(): Promise<{\r\n type: string;\r\n description?: string;\r\n } | null> {\r\n if (!this.serverUrl) {\r\n return null;\r\n }\r\n\r\n try {\r\n const response = await fetch(`${this.serverUrl}/interface-info`);\r\n\r\n if (!response.ok) {\r\n console.warn(`Interface info request failed: ${response.statusText}`);\r\n return null;\r\n }\r\n\r\n return await response.json();\r\n } catch (error) {\r\n console.error('Failed to get interface info:', error);\r\n return null;\r\n }\r\n }\r\n}\r\n"],"names":["RemoteExecutionAdapter","BasePlaygroundAdapter","value","action","needsStructuredParams","schema","shape","missingFields","Object","key","_fieldDef__def","_fieldDef__def1","fieldDef","isOptional","undefined","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","requestId","encodeURIComponent","callback","lastTip","interval","setInterval","_progress_tip","progress","clearInterval","serverUrl","Map"],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { findAllMidsceneLocatorField } from "@sqaitech/core/ai-model";
|
|
2
|
+
import { buildDetailedLocateParam } from "@sqaitech/core/yaml";
|
|
3
|
+
const dataExtractionAPIs = [
|
|
4
|
+
'aiQuery',
|
|
5
|
+
'aiBoolean',
|
|
6
|
+
'aiNumber',
|
|
7
|
+
'aiString',
|
|
8
|
+
'aiAsk'
|
|
9
|
+
];
|
|
10
|
+
const validationAPIs = [
|
|
11
|
+
'aiAssert',
|
|
12
|
+
'aiWaitFor'
|
|
13
|
+
];
|
|
14
|
+
const noReplayAPIs = [
|
|
15
|
+
...dataExtractionAPIs,
|
|
16
|
+
...validationAPIs
|
|
17
|
+
];
|
|
18
|
+
const formatErrorMessage = (e)=>{
|
|
19
|
+
const errorMessage = (null == e ? void 0 : e.message) || '';
|
|
20
|
+
if (errorMessage.includes('of different extension')) return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://sqai.tech/quick-experience.html#faq';
|
|
21
|
+
if (errorMessage.includes('NOT_IMPLEMENTED_AS_DESIGNED')) return 'Further actions cannot be performed in the current environment';
|
|
22
|
+
return errorMessage || 'Unknown error';
|
|
23
|
+
};
|
|
24
|
+
async function parseStructuredParams(action, params, options = {}) {
|
|
25
|
+
if (!(null == action ? void 0 : action.paramSchema) || !('shape' in action.paramSchema)) return [
|
|
26
|
+
params.prompt || '',
|
|
27
|
+
options
|
|
28
|
+
];
|
|
29
|
+
const schema = action.paramSchema;
|
|
30
|
+
const keys = schema && 'shape' in schema ? Object.keys(schema.shape) : [];
|
|
31
|
+
const paramObj = {
|
|
32
|
+
...options
|
|
33
|
+
};
|
|
34
|
+
keys.forEach((key)=>{
|
|
35
|
+
if (void 0 !== params[key] && null !== params[key] && '' !== params[key]) paramObj[key] = params[key];
|
|
36
|
+
});
|
|
37
|
+
if (schema) {
|
|
38
|
+
const locatorFieldKeys = findAllMidsceneLocatorField(schema);
|
|
39
|
+
locatorFieldKeys.forEach((locateKey)=>{
|
|
40
|
+
const locatePrompt = params[locateKey];
|
|
41
|
+
if (locatePrompt && 'string' == typeof locatePrompt) {
|
|
42
|
+
const detailedLocateParam = buildDetailedLocateParam(locatePrompt, {
|
|
43
|
+
deepThink: options.deepThink,
|
|
44
|
+
cacheable: true
|
|
45
|
+
});
|
|
46
|
+
if (detailedLocateParam) paramObj[locateKey] = detailedLocateParam;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return [
|
|
51
|
+
paramObj
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
function validateStructuredParams(value, action) {
|
|
55
|
+
if (!value.params) return {
|
|
56
|
+
valid: false,
|
|
57
|
+
errorMessage: 'Parameters are required'
|
|
58
|
+
};
|
|
59
|
+
if (!(null == action ? void 0 : action.paramSchema)) return {
|
|
60
|
+
valid: true
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
var _action_paramSchema;
|
|
64
|
+
const paramsForValidation = {
|
|
65
|
+
...value.params
|
|
66
|
+
};
|
|
67
|
+
const schema = action.paramSchema;
|
|
68
|
+
if (schema) {
|
|
69
|
+
const locatorFieldKeys = findAllMidsceneLocatorField(schema);
|
|
70
|
+
locatorFieldKeys.forEach((key)=>{
|
|
71
|
+
if ('string' == typeof paramsForValidation[key]) paramsForValidation[key] = {
|
|
72
|
+
midscene_location_field_flag: true,
|
|
73
|
+
prompt: paramsForValidation[key],
|
|
74
|
+
center: [
|
|
75
|
+
0,
|
|
76
|
+
0
|
|
77
|
+
],
|
|
78
|
+
rect: {
|
|
79
|
+
left: 0,
|
|
80
|
+
top: 0,
|
|
81
|
+
width: 0,
|
|
82
|
+
height: 0
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
null == (_action_paramSchema = action.paramSchema) || _action_paramSchema.parse(paramsForValidation);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
const zodError = error;
|
|
90
|
+
if (zodError.errors && zodError.errors.length > 0) {
|
|
91
|
+
const errorMessages = zodError.errors.filter((err)=>{
|
|
92
|
+
const path = err.path.join('.');
|
|
93
|
+
return !path.includes('center') && !path.includes('rect') && !path.includes('midscene_location_field_flag');
|
|
94
|
+
}).map((err)=>{
|
|
95
|
+
const field = err.path.join('.');
|
|
96
|
+
return `${field}: ${err.message}`;
|
|
97
|
+
});
|
|
98
|
+
if (errorMessages.length > 0) return {
|
|
99
|
+
valid: false,
|
|
100
|
+
errorMessage: `Validation error: ${errorMessages.join(', ')}`
|
|
101
|
+
};
|
|
102
|
+
} else {
|
|
103
|
+
const errorMsg = error instanceof Error ? error.message : 'Unknown validation error';
|
|
104
|
+
return {
|
|
105
|
+
valid: false,
|
|
106
|
+
errorMessage: `Parameter validation failed: ${errorMsg}`
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
valid: true
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async function executeAction(activeAgent, actionType, actionSpace, value, options) {
|
|
115
|
+
const action = null == actionSpace ? void 0 : actionSpace.find((a)=>a.interfaceAlias === actionType || a.name === actionType);
|
|
116
|
+
if (action && 'function' == typeof activeAgent.callActionInActionSpace) if (value.params) {
|
|
117
|
+
const parsedParams = await parseStructuredParams(action, value.params, options);
|
|
118
|
+
return await activeAgent.callActionInActionSpace(action.name, parsedParams[0]);
|
|
119
|
+
} else {
|
|
120
|
+
const detailedLocateParam = value.prompt ? buildDetailedLocateParam(value.prompt, {
|
|
121
|
+
deepThink: options.deepThink,
|
|
122
|
+
cacheable: true
|
|
123
|
+
}) : void 0;
|
|
124
|
+
return await activeAgent.callActionInActionSpace(action.name, {
|
|
125
|
+
locate: detailedLocateParam,
|
|
126
|
+
...options
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
{
|
|
130
|
+
const prompt = value.prompt;
|
|
131
|
+
if ('aiAssert' === actionType) {
|
|
132
|
+
var _activeAgent_aiAssert;
|
|
133
|
+
const { pass, thought } = await (null == activeAgent ? void 0 : null == (_activeAgent_aiAssert = activeAgent.aiAssert) ? void 0 : _activeAgent_aiAssert.call(activeAgent, prompt || '', void 0, {
|
|
134
|
+
keepRawResponse: true,
|
|
135
|
+
...options
|
|
136
|
+
})) || {};
|
|
137
|
+
return {
|
|
138
|
+
pass: pass || false,
|
|
139
|
+
thought: thought || ''
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (activeAgent && 'function' == typeof activeAgent[actionType]) return await activeAgent[actionType](prompt, options);
|
|
143
|
+
throw new Error(`Unknown action type: ${actionType}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export { dataExtractionAPIs, executeAction, formatErrorMessage, noReplayAPIs, parseStructuredParams, validateStructuredParams, validationAPIs };
|
|
147
|
+
|
|
148
|
+
//# sourceMappingURL=common.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.mjs","sources":["webpack://@sqaitech/playground/./src/common.ts"],"sourcesContent":["import type { DeviceAction } from '@sqaitech/core';\r\nimport { findAllMidsceneLocatorField } from '@sqaitech/core/ai-model';\r\nimport { buildDetailedLocateParam } from '@sqaitech/core/yaml';\r\nimport type {\r\n ExecutionOptions,\r\n FormValue,\r\n PlaygroundAgent,\r\n ValidationResult,\r\n} from './types';\r\n\r\n// APIs that should not generate replay scripts\r\nexport const dataExtractionAPIs = [\r\n 'aiQuery',\r\n 'aiBoolean',\r\n 'aiNumber',\r\n 'aiString',\r\n 'aiAsk',\r\n];\r\n\r\nexport const validationAPIs = ['aiAssert', 'aiWaitFor'];\r\n\r\nexport const noReplayAPIs = [...dataExtractionAPIs, ...validationAPIs];\r\n\r\nexport const formatErrorMessage = (e: any): string => {\r\n const errorMessage = e?.message || '';\r\n\r\n if (errorMessage.includes('of different extension')) {\r\n return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://sqai.tech/quick-experience.html#faq';\r\n }\r\n\r\n if (errorMessage.includes('NOT_IMPLEMENTED_AS_DESIGNED')) {\r\n return 'Further actions cannot be performed in the current environment';\r\n }\r\n\r\n return errorMessage || 'Unknown error';\r\n};\r\n\r\n// Parse structured parameters for callActionInActionSpace\r\nexport async function parseStructuredParams(\r\n action: DeviceAction<unknown>,\r\n params: Record<string, unknown>,\r\n options: ExecutionOptions = {},\r\n): Promise<unknown[]> {\r\n if (!action?.paramSchema || !('shape' in action.paramSchema)) {\r\n return [params.prompt || '', options];\r\n }\r\n\r\n const schema = action.paramSchema;\r\n const keys =\r\n schema && 'shape' in schema\r\n ? Object.keys((schema as { shape: Record<string, unknown> }).shape)\r\n : [];\r\n\r\n const paramObj: Record<string, unknown> = { ...options };\r\n\r\n keys.forEach((key) => {\r\n if (\r\n params[key] !== undefined &&\r\n params[key] !== null &&\r\n params[key] !== ''\r\n ) {\r\n paramObj[key] = params[key];\r\n }\r\n });\r\n\r\n // Check if there's a locate field that needs detailed locate param processing\r\n if (schema) {\r\n const locatorFieldKeys = findAllMidsceneLocatorField(schema);\r\n locatorFieldKeys.forEach((locateKey: string) => {\r\n const locatePrompt = params[locateKey];\r\n if (locatePrompt && typeof locatePrompt === 'string') {\r\n // Build detailed locate param using the locate prompt and options\r\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, {\r\n deepThink: options.deepThink,\r\n cacheable: true, // Default to true for playground\r\n });\r\n if (detailedLocateParam) {\r\n paramObj[locateKey] = detailedLocateParam;\r\n }\r\n }\r\n });\r\n }\r\n\r\n return [paramObj];\r\n}\r\n\r\nexport function validateStructuredParams(\r\n value: FormValue,\r\n action: DeviceAction<unknown> | undefined,\r\n): ValidationResult {\r\n if (!value.params) {\r\n return { valid: false, errorMessage: 'Parameters are required' };\r\n }\r\n\r\n if (!action?.paramSchema) {\r\n return { valid: true };\r\n }\r\n\r\n try {\r\n const paramsForValidation = { ...value.params };\r\n\r\n const schema = action.paramSchema;\r\n if (schema) {\r\n const locatorFieldKeys = findAllMidsceneLocatorField(schema);\r\n locatorFieldKeys.forEach((key: string) => {\r\n if (typeof paramsForValidation[key] === 'string') {\r\n paramsForValidation[key] = {\r\n midscene_location_field_flag: true,\r\n prompt: paramsForValidation[key],\r\n center: [0, 0],\r\n rect: { left: 0, top: 0, width: 0, height: 0 },\r\n };\r\n }\r\n });\r\n }\r\n\r\n action.paramSchema?.parse(paramsForValidation);\r\n return { valid: true };\r\n } catch (error: unknown) {\r\n const zodError = error as {\r\n errors?: Array<{ path: string[]; message: string }>;\r\n };\r\n if (zodError.errors && zodError.errors.length > 0) {\r\n const errorMessages = zodError.errors\r\n .filter((err) => {\r\n const path = err.path.join('.');\r\n return (\r\n !path.includes('center') &&\r\n !path.includes('rect') &&\r\n !path.includes('midscene_location_field_flag')\r\n );\r\n })\r\n .map((err) => {\r\n const field = err.path.join('.');\r\n return `${field}: ${err.message}`;\r\n });\r\n\r\n if (errorMessages.length > 0) {\r\n return {\r\n valid: false,\r\n errorMessage: `Validation error: ${errorMessages.join(', ')}`,\r\n };\r\n }\r\n } else {\r\n const errorMsg =\r\n error instanceof Error ? error.message : 'Unknown validation error';\r\n return {\r\n valid: false,\r\n errorMessage: `Parameter validation failed: ${errorMsg}`,\r\n };\r\n }\r\n }\r\n\r\n return { valid: true };\r\n}\r\n\r\nexport async function executeAction(\r\n activeAgent: PlaygroundAgent,\r\n actionType: string,\r\n actionSpace: DeviceAction<unknown>[],\r\n value: FormValue,\r\n options: ExecutionOptions,\r\n): Promise<unknown> {\r\n const action = actionSpace?.find(\r\n (a: DeviceAction<unknown>) =>\r\n a.interfaceAlias === actionType || a.name === actionType,\r\n );\r\n\r\n if (action && typeof activeAgent.callActionInActionSpace === 'function') {\r\n if (value.params) {\r\n const parsedParams = await parseStructuredParams(\r\n action,\r\n value.params,\r\n options,\r\n );\r\n return await activeAgent.callActionInActionSpace(\r\n action.name,\r\n parsedParams[0],\r\n );\r\n } else {\r\n // For prompt-based actions, we need to build the detailed locate param\r\n const detailedLocateParam = value.prompt\r\n ? buildDetailedLocateParam(value.prompt, {\r\n deepThink: options.deepThink,\r\n cacheable: true,\r\n })\r\n : undefined;\r\n\r\n return await activeAgent.callActionInActionSpace(action.name, {\r\n locate: detailedLocateParam,\r\n ...options,\r\n });\r\n }\r\n } else {\r\n const prompt = value.prompt;\r\n\r\n if (actionType === 'aiAssert') {\r\n const { pass, thought } =\r\n (await activeAgent?.aiAssert?.(prompt || '', undefined, {\r\n keepRawResponse: true,\r\n ...options,\r\n })) || {};\r\n return { pass: pass || false, thought: thought || '' };\r\n }\r\n\r\n // Fallback for methods not found in actionSpace\r\n if (activeAgent && typeof activeAgent[actionType] === 'function') {\r\n return await activeAgent[actionType](prompt, options);\r\n }\r\n\r\n throw new Error(`Unknown action type: ${actionType}`);\r\n }\r\n}\r\n"],"names":["dataExtractionAPIs","validationAPIs","noReplayAPIs","formatErrorMessage","e","errorMessage","parseStructuredParams","action","params","options","schema","keys","Object","paramObj","key","undefined","locatorFieldKeys","findAllMidsceneLocatorField","locateKey","locatePrompt","detailedLocateParam","buildDetailedLocateParam","validateStructuredParams","value","_action_paramSchema","paramsForValidation","error","zodError","errorMessages","err","path","field","errorMsg","Error","executeAction","activeAgent","actionType","actionSpace","a","parsedParams","prompt","pass","thought"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { dataExtractionAPIs, executeAction, formatErrorMessage, noReplayAPIs, validateStructuredParams, validationAPIs } from "./common.mjs";
|
|
2
|
+
import { PlaygroundSDK } from "./sdk/index.mjs";
|
|
3
|
+
import { BasePlaygroundAdapter } from "./adapters/base.mjs";
|
|
4
|
+
import { LocalExecutionAdapter } from "./adapters/local-execution.mjs";
|
|
5
|
+
import { RemoteExecutionAdapter } from "./adapters/remote-execution.mjs";
|
|
6
|
+
const PlaygroundServer = void 0;
|
|
7
|
+
export { BasePlaygroundAdapter, LocalExecutionAdapter, PlaygroundSDK, PlaygroundServer, RemoteExecutionAdapter, dataExtractionAPIs, executeAction, formatErrorMessage, noReplayAPIs, validateStructuredParams, validationAPIs };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=index.browser.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.browser.mjs","sources":["webpack://@sqaitech/playground/./src/index.browser.ts"],"sourcesContent":["// Browser-safe version of playground exports (excludes server)\r\nexport {\r\n dataExtractionAPIs,\r\n noReplayAPIs,\r\n validationAPIs,\r\n formatErrorMessage,\r\n validateStructuredParams,\r\n executeAction,\r\n} from './common';\r\n\r\n// SDK exports (all browser-safe)\r\nexport { PlaygroundSDK } from './sdk';\r\nexport { BasePlaygroundAdapter } from './adapters/base';\r\nexport { LocalExecutionAdapter } from './adapters/local-execution';\r\nexport { RemoteExecutionAdapter } from './adapters/remote-execution';\r\n\r\n// PlaygroundServer is not available in browser environments\r\nexport const PlaygroundServer = undefined;\r\n\r\nexport type {\r\n ExecutionOptions,\r\n FormValue,\r\n PlaygroundAgent,\r\n ValidationResult,\r\n PlaygroundConfig,\r\n ExecutionType,\r\n PlaygroundAdapter,\r\n} from './types';\r\n"],"names":["PlaygroundServer","undefined"],"mappings":";;;;;AAiBO,MAAMA,mBAAmBC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { dataExtractionAPIs, executeAction, formatErrorMessage, noReplayAPIs, validateStructuredParams, validationAPIs } from "./common.mjs";
|
|
2
|
+
import { PlaygroundServer } from "./server.mjs";
|
|
3
|
+
import { playgroundForAgent } from "./launcher.mjs";
|
|
4
|
+
import { PlaygroundSDK } from "./sdk/index.mjs";
|
|
5
|
+
import { BasePlaygroundAdapter } from "./adapters/base.mjs";
|
|
6
|
+
import { LocalExecutionAdapter } from "./adapters/local-execution.mjs";
|
|
7
|
+
import { RemoteExecutionAdapter } from "./adapters/remote-execution.mjs";
|
|
8
|
+
export { BasePlaygroundAdapter, LocalExecutionAdapter, PlaygroundSDK, PlaygroundServer, RemoteExecutionAdapter, dataExtractionAPIs, executeAction, formatErrorMessage, noReplayAPIs, playgroundForAgent, validateStructuredParams, validationAPIs };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { PLAYGROUND_SERVER_PORT } from "@sqaitech/shared/constants";
|
|
3
|
+
import cors from "cors";
|
|
4
|
+
import server_0 from "./server.mjs";
|
|
5
|
+
function playgroundForAgent(agent) {
|
|
6
|
+
return {
|
|
7
|
+
async launch (options = {}) {
|
|
8
|
+
const { port = PLAYGROUND_SERVER_PORT, openBrowser = true, browserCommand, verbose = true, id, enableCors = false, corsOptions = {
|
|
9
|
+
origin: '*',
|
|
10
|
+
credentials: true
|
|
11
|
+
} } = options;
|
|
12
|
+
const webPage = agent.interface;
|
|
13
|
+
if (!webPage) throw new Error('Agent must have an interface property');
|
|
14
|
+
if (verbose) {
|
|
15
|
+
console.log("\uD83D\uDE80 Starting Midscene Playground...");
|
|
16
|
+
console.log(`\u{1F4F1} Agent: ${agent.constructor.name}`);
|
|
17
|
+
console.log(`\u{1F5A5}\u{FE0F} Page: ${webPage.constructor.name}`);
|
|
18
|
+
console.log(`\u{1F310} Port: ${port}`);
|
|
19
|
+
if (enableCors) console.log("\uD83D\uDD13 CORS enabled");
|
|
20
|
+
}
|
|
21
|
+
const server = new server_0(agent, void 0, id);
|
|
22
|
+
if (enableCors) server.app.use(cors(corsOptions));
|
|
23
|
+
const launchedServer = await server.launch(port);
|
|
24
|
+
if (verbose) console.log(`\u{2705} Playground server started on port ${port}`);
|
|
25
|
+
const url = `http://127.0.0.1:${port}`;
|
|
26
|
+
if (openBrowser) await openInBrowser(url, browserCommand, verbose);
|
|
27
|
+
return {
|
|
28
|
+
server: launchedServer,
|
|
29
|
+
port,
|
|
30
|
+
host: '127.0.0.1',
|
|
31
|
+
close: async ()=>{
|
|
32
|
+
if (verbose) console.log("\uD83D\uDED1 Shutting down Midscene Playground...");
|
|
33
|
+
try {
|
|
34
|
+
await launchedServer.close();
|
|
35
|
+
if (verbose) console.log("\u2705 Playground shutdown complete");
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (verbose) console.error("\u274C Error during playground shutdown:", error);
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function openInBrowser(url, customCommand, verbose = true) {
|
|
46
|
+
return new Promise((resolve, reject)=>{
|
|
47
|
+
let command;
|
|
48
|
+
let args;
|
|
49
|
+
if (customCommand) {
|
|
50
|
+
command = customCommand;
|
|
51
|
+
args = [
|
|
52
|
+
url
|
|
53
|
+
];
|
|
54
|
+
} else switch(process.platform){
|
|
55
|
+
case 'darwin':
|
|
56
|
+
command = 'open';
|
|
57
|
+
args = [
|
|
58
|
+
url
|
|
59
|
+
];
|
|
60
|
+
break;
|
|
61
|
+
case 'win32':
|
|
62
|
+
command = 'start';
|
|
63
|
+
args = [
|
|
64
|
+
'',
|
|
65
|
+
url
|
|
66
|
+
];
|
|
67
|
+
break;
|
|
68
|
+
default:
|
|
69
|
+
command = 'xdg-open';
|
|
70
|
+
args = [
|
|
71
|
+
url
|
|
72
|
+
];
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
if (verbose) console.log(`\u{1F310} Opening browser: ${command} ${args.join(' ')}`);
|
|
76
|
+
const child = spawn(command, args, {
|
|
77
|
+
detached: true,
|
|
78
|
+
stdio: 'ignore'
|
|
79
|
+
});
|
|
80
|
+
child.on('error', (error)=>{
|
|
81
|
+
if (verbose) {
|
|
82
|
+
console.warn("\u26A0\uFE0F Failed to open browser automatically:", error.message);
|
|
83
|
+
console.log(`\u{1F310} Please open manually: ${url}`);
|
|
84
|
+
}
|
|
85
|
+
resolve();
|
|
86
|
+
});
|
|
87
|
+
child.on('close', ()=>{
|
|
88
|
+
resolve();
|
|
89
|
+
});
|
|
90
|
+
child.unref();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
export { playgroundForAgent };
|
|
94
|
+
|
|
95
|
+
//# sourceMappingURL=launcher.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.mjs","sources":["webpack://@sqaitech/playground/./src/launcher.ts"],"sourcesContent":["import { spawn } from 'node:child_process';\r\nimport type { Agent, Agent as PageAgent } from '@sqaitech/core/agent';\r\nimport { PLAYGROUND_SERVER_PORT } from '@sqaitech/shared/constants';\r\nimport cors from 'cors';\r\nimport PlaygroundServer from './server';\r\n\r\nexport interface LaunchPlaygroundOptions {\r\n /**\r\n * Port to start the playground server on\r\n * @default 5800\r\n */\r\n port?: number;\r\n\r\n /**\r\n * Whether to automatically open the playground in browser\r\n * @default true\r\n */\r\n openBrowser?: boolean;\r\n\r\n /**\r\n * Custom browser command to open playground\r\n * @default 'open' on macOS, 'start' on Windows, 'xdg-open' on Linux\r\n */\r\n browserCommand?: string;\r\n\r\n /**\r\n * Whether to show server logs\r\n * @default true\r\n */\r\n verbose?: boolean;\r\n\r\n /**\r\n * Fixed ID for the playground server instance\r\n * If provided, the same ID will be used across restarts,\r\n * allowing chat history to persist\r\n * @default undefined (generates random UUID)\r\n */\r\n id?: string;\r\n\r\n /**\r\n * Whether to enable CORS (Cross-Origin Resource Sharing)\r\n * @default false\r\n */\r\n enableCors?: boolean;\r\n\r\n /**\r\n * CORS configuration options\r\n * @default { origin: '*', credentials: true } when enableCors is true\r\n */\r\n corsOptions?: {\r\n origin?: string | boolean | string[];\r\n credentials?: boolean;\r\n methods?: string[];\r\n allowedHeaders?: string[];\r\n };\r\n}\r\n\r\nexport interface LaunchPlaygroundResult {\r\n /**\r\n * The playground server instance\r\n */\r\n server: PlaygroundServer;\r\n\r\n /**\r\n * The server port\r\n */\r\n port: number;\r\n\r\n /**\r\n * The server host\r\n */\r\n host: string;\r\n\r\n /**\r\n * Function to gracefully shutdown the playground\r\n */\r\n close: () => Promise<void>;\r\n}\r\n\r\n/**\r\n * Create a playground launcher for a specific agent\r\n *\r\n * @example\r\n * ```typescript\r\n * import { playgroundForAgent } from '@sqaitech/playground';\r\n * import { SampleDevice, Agent } from '@sqaitech/core';\r\n *\r\n * const device = new SampleDevice();\r\n * const agent = new Agent(device);\r\n *\r\n * // Launch playground for the agent\r\n * const server = await playgroundForAgent(agent).launch();\r\n *\r\n * // Launch with CORS enabled\r\n * const serverWithCors = await playgroundForAgent(agent).launch({\r\n * enableCors: true,\r\n * corsOptions: {\r\n * origin: ['http://localhost:3000', 'http://localhost:8080'],\r\n * credentials: true\r\n * }\r\n * });\r\n *\r\n * // Later, when you want to shutdown:\r\n * server.close();\r\n * ```\r\n */\r\nexport function playgroundForAgent(agent: Agent) {\r\n return {\r\n /**\r\n * Launch the playground server with optional configuration\r\n */\r\n async launch(\r\n options: LaunchPlaygroundOptions = {},\r\n ): Promise<LaunchPlaygroundResult> {\r\n const {\r\n port = PLAYGROUND_SERVER_PORT,\r\n openBrowser = true,\r\n browserCommand,\r\n verbose = true,\r\n id,\r\n enableCors = false,\r\n corsOptions = { origin: '*', credentials: true },\r\n } = options;\r\n\r\n // Extract agent components - Agent has interface property\r\n const webPage = agent.interface;\r\n if (!webPage) {\r\n throw new Error('Agent must have an interface property');\r\n }\r\n\r\n if (verbose) {\r\n console.log('🚀 Starting Midscene Playground...');\r\n console.log(`📱 Agent: ${agent.constructor.name}`);\r\n console.log(`🖥️ Page: ${webPage.constructor.name}`);\r\n console.log(`🌐 Port: ${port}`);\r\n if (enableCors) {\r\n console.log('🔓 CORS enabled');\r\n }\r\n }\r\n\r\n // Create and launch the server with agent instance\r\n const server = new PlaygroundServer(\r\n agent as unknown as PageAgent,\r\n undefined, // staticPath - use default\r\n id, // Optional override ID (usually not needed now)\r\n );\r\n\r\n // Register CORS middleware if enabled\r\n if (enableCors) {\r\n server.app.use(cors(corsOptions));\r\n }\r\n\r\n const launchedServer = (await server.launch(port)) as PlaygroundServer;\r\n\r\n if (verbose) {\r\n console.log(`✅ Playground server started on port ${port}`);\r\n }\r\n\r\n const url = `http://127.0.0.1:${port}`;\r\n\r\n // Open browser if requested\r\n if (openBrowser) {\r\n await openInBrowser(url, browserCommand, verbose);\r\n }\r\n\r\n return {\r\n server: launchedServer,\r\n port,\r\n host: '127.0.0.1',\r\n close: async () => {\r\n if (verbose) {\r\n console.log('🛑 Shutting down Midscene Playground...');\r\n }\r\n\r\n try {\r\n await launchedServer.close();\r\n if (verbose) {\r\n console.log('✅ Playground shutdown complete');\r\n }\r\n } catch (error) {\r\n if (verbose) {\r\n console.error('❌ Error during playground shutdown:', error);\r\n }\r\n throw error;\r\n }\r\n },\r\n };\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Open URL in browser using platform-appropriate command\r\n */\r\nasync function openInBrowser(\r\n url: string,\r\n customCommand?: string,\r\n verbose = true,\r\n): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n let command: string;\r\n let args: string[];\r\n\r\n if (customCommand) {\r\n command = customCommand;\r\n args = [url];\r\n } else {\r\n // Detect platform and use appropriate command\r\n switch (process.platform) {\r\n case 'darwin':\r\n command = 'open';\r\n args = [url];\r\n break;\r\n case 'win32':\r\n command = 'start';\r\n args = ['', url]; // Empty string for title\r\n break;\r\n default:\r\n command = 'xdg-open';\r\n args = [url];\r\n break;\r\n }\r\n }\r\n\r\n if (verbose) {\r\n console.log(`🌐 Opening browser: ${command} ${args.join(' ')}`);\r\n }\r\n\r\n const child = spawn(command, args, {\r\n detached: true,\r\n stdio: 'ignore',\r\n });\r\n\r\n child.on('error', (error) => {\r\n if (verbose) {\r\n console.warn('⚠️ Failed to open browser automatically:', error.message);\r\n console.log(`🌐 Please open manually: ${url}`);\r\n }\r\n // Don't reject, just continue - browser opening is optional\r\n resolve();\r\n });\r\n\r\n child.on('close', () => {\r\n resolve();\r\n });\r\n\r\n // Don't wait for the browser process\r\n child.unref();\r\n });\r\n}\r\n"],"names":["playgroundForAgent","agent","options","port","PLAYGROUND_SERVER_PORT","openBrowser","browserCommand","verbose","id","enableCors","corsOptions","webPage","Error","console","server","PlaygroundServer","undefined","cors","launchedServer","url","openInBrowser","error","customCommand","Promise","resolve","reject","command","args","process","child","spawn"],"mappings":";;;;AA0GO,SAASA,mBAAmBC,KAAY;IAC7C,OAAO;QAIL,MAAM,QACJC,UAAmC,CAAC,CAAC;YAErC,MAAM,EACJC,OAAOC,sBAAsB,EAC7BC,cAAc,IAAI,EAClBC,cAAc,EACdC,UAAU,IAAI,EACdC,EAAE,EACFC,aAAa,KAAK,EAClBC,cAAc;gBAAE,QAAQ;gBAAK,aAAa;YAAK,CAAC,EACjD,GAAGR;YAGJ,MAAMS,UAAUV,MAAM,SAAS;YAC/B,IAAI,CAACU,SACH,MAAM,IAAIC,MAAM;YAGlB,IAAIL,SAAS;gBACXM,QAAQ,GAAG,CAAC;gBACZA,QAAQ,GAAG,CAAC,CAAC,iBAAU,EAAEZ,MAAM,WAAW,CAAC,IAAI,EAAE;gBACjDY,QAAQ,GAAG,CAAC,CAAC,wBAAU,EAAEF,QAAQ,WAAW,CAAC,IAAI,EAAE;gBACnDE,QAAQ,GAAG,CAAC,CAAC,gBAAS,EAAEV,MAAM;gBAC9B,IAAIM,YACFI,QAAQ,GAAG,CAAC;YAEhB;YAGA,MAAMC,SAAS,IAAIC,SACjBd,OACAe,QACAR;YAIF,IAAIC,YACFK,OAAO,GAAG,CAAC,GAAG,CAACG,KAAKP;YAGtB,MAAMQ,iBAAkB,MAAMJ,OAAO,MAAM,CAACX;YAE5C,IAAII,SACFM,QAAQ,GAAG,CAAC,CAAC,2CAAoC,EAAEV,MAAM;YAG3D,MAAMgB,MAAM,CAAC,iBAAiB,EAAEhB,MAAM;YAGtC,IAAIE,aACF,MAAMe,cAAcD,KAAKb,gBAAgBC;YAG3C,OAAO;gBACL,QAAQW;gBACRf;gBACA,MAAM;gBACN,OAAO;oBACL,IAAII,SACFM,QAAQ,GAAG,CAAC;oBAGd,IAAI;wBACF,MAAMK,eAAe,KAAK;wBAC1B,IAAIX,SACFM,QAAQ,GAAG,CAAC;oBAEhB,EAAE,OAAOQ,OAAO;wBACd,IAAId,SACFM,QAAQ,KAAK,CAAC,4CAAuCQ;wBAEvD,MAAMA;oBACR;gBACF;YACF;QACF;IACF;AACF;AAKA,eAAeD,cACbD,GAAW,EACXG,aAAsB,EACtBf,UAAU,IAAI;IAEd,OAAO,IAAIgB,QAAQ,CAACC,SAASC;QAC3B,IAAIC;QACJ,IAAIC;QAEJ,IAAIL,eAAe;YACjBI,UAAUJ;YACVK,OAAO;gBAACR;aAAI;QACd,OAEE,OAAQS,QAAQ,QAAQ;YACtB,KAAK;gBACHF,UAAU;gBACVC,OAAO;oBAACR;iBAAI;gBACZ;YACF,KAAK;gBACHO,UAAU;gBACVC,OAAO;oBAAC;oBAAIR;iBAAI;gBAChB;YACF;gBACEO,UAAU;gBACVC,OAAO;oBAACR;iBAAI;gBACZ;QACJ;QAGF,IAAIZ,SACFM,QAAQ,GAAG,CAAC,CAAC,2BAAoB,EAAEa,QAAQ,CAAC,EAAEC,KAAK,IAAI,CAAC,MAAM;QAGhE,MAAME,QAAQC,MAAMJ,SAASC,MAAM;YACjC,UAAU;YACV,OAAO;QACT;QAEAE,MAAM,EAAE,CAAC,SAAS,CAACR;YACjB,IAAId,SAAS;gBACXM,QAAQ,IAAI,CAAC,uDAA6CQ,MAAM,OAAO;gBACvER,QAAQ,GAAG,CAAC,CAAC,gCAAyB,EAAEM,KAAK;YAC/C;YAEAK;QACF;QAEAK,MAAM,EAAE,CAAC,SAAS;YAChBL;QACF;QAGAK,MAAM,KAAK;IACb;AACF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { PLAYGROUND_SERVER_PORT } from "@sqaitech/shared/constants";
|
|
2
|
+
import { LocalExecutionAdapter } from "../adapters/local-execution.mjs";
|
|
3
|
+
import { RemoteExecutionAdapter } from "../adapters/remote-execution.mjs";
|
|
4
|
+
function _define_property(obj, key, value) {
|
|
5
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
6
|
+
value: value,
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true
|
|
10
|
+
});
|
|
11
|
+
else obj[key] = value;
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
class PlaygroundSDK {
|
|
15
|
+
createAdapter(type, serverUrl, agent) {
|
|
16
|
+
switch(type){
|
|
17
|
+
case 'local-execution':
|
|
18
|
+
if (!agent) throw new Error('Agent is required for local execution');
|
|
19
|
+
return new LocalExecutionAdapter(agent);
|
|
20
|
+
case 'remote-execution':
|
|
21
|
+
{
|
|
22
|
+
const finalServerUrl = serverUrl || ('undefined' != typeof window && window.location.protocol.includes('http') ? window.location.origin : `http://localhost:${PLAYGROUND_SERVER_PORT}`);
|
|
23
|
+
return new RemoteExecutionAdapter(finalServerUrl);
|
|
24
|
+
}
|
|
25
|
+
default:
|
|
26
|
+
throw new Error(`Unsupported execution type: ${type}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async executeAction(actionType, value, options) {
|
|
30
|
+
const result = await this.adapter.executeAction(actionType, value, options);
|
|
31
|
+
if (options.requestId) this.stopProgressPolling(options.requestId);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
async getActionSpace(context) {
|
|
35
|
+
return this.adapter.getActionSpace(context);
|
|
36
|
+
}
|
|
37
|
+
validateStructuredParams(value, action) {
|
|
38
|
+
return this.adapter.validateParams(value, action);
|
|
39
|
+
}
|
|
40
|
+
formatErrorMessage(error) {
|
|
41
|
+
return this.adapter.formatErrorMessage(error);
|
|
42
|
+
}
|
|
43
|
+
createDisplayContent(value, needsStructuredParams, action) {
|
|
44
|
+
return this.adapter.createDisplayContent(value, needsStructuredParams, action);
|
|
45
|
+
}
|
|
46
|
+
get id() {
|
|
47
|
+
if (this.adapter instanceof RemoteExecutionAdapter) return this.adapter.id;
|
|
48
|
+
if (this.adapter instanceof LocalExecutionAdapter) return this.adapter.id;
|
|
49
|
+
}
|
|
50
|
+
async checkStatus() {
|
|
51
|
+
if (this.adapter instanceof RemoteExecutionAdapter) return this.adapter.checkStatus();
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
async overrideConfig(aiConfig) {
|
|
55
|
+
if (this.adapter instanceof RemoteExecutionAdapter) return this.adapter.overrideConfig(aiConfig);
|
|
56
|
+
}
|
|
57
|
+
async getTaskProgress(requestId) {
|
|
58
|
+
if (this.adapter instanceof RemoteExecutionAdapter) return this.adapter.getTaskProgress(requestId);
|
|
59
|
+
if (this.adapter instanceof LocalExecutionAdapter) return this.adapter.getTaskProgress(requestId);
|
|
60
|
+
return {
|
|
61
|
+
tip: void 0
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async cancelTask(requestId) {
|
|
65
|
+
this.stopProgressPolling(requestId);
|
|
66
|
+
if (this.adapter instanceof RemoteExecutionAdapter) return this.adapter.cancelTask(requestId);
|
|
67
|
+
return {
|
|
68
|
+
error: 'Cancel task not supported in local execution mode'
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
onProgressUpdate(callback) {
|
|
72
|
+
if (this.adapter instanceof RemoteExecutionAdapter) this.adapter.setProgressCallback(callback);
|
|
73
|
+
else if (this.adapter instanceof LocalExecutionAdapter) this.adapter.setProgressCallback(callback);
|
|
74
|
+
}
|
|
75
|
+
startProgressPolling(requestId) {
|
|
76
|
+
console.warn('startProgressPolling is deprecated - polling is now automatic');
|
|
77
|
+
}
|
|
78
|
+
stopProgressPolling(requestId) {
|
|
79
|
+
console.warn('stopProgressPolling is deprecated - polling cleanup is now automatic');
|
|
80
|
+
}
|
|
81
|
+
async cancelExecution(requestId) {
|
|
82
|
+
this.stopProgressPolling(requestId);
|
|
83
|
+
if (this.adapter instanceof RemoteExecutionAdapter) await this.adapter.cancelTask(requestId);
|
|
84
|
+
else if (this.adapter instanceof LocalExecutionAdapter) console.warn('Local execution cancellation not fully implemented');
|
|
85
|
+
}
|
|
86
|
+
async getScreenshot() {
|
|
87
|
+
if (this.adapter instanceof RemoteExecutionAdapter) return this.adapter.getScreenshot();
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
async getInterfaceInfo() {
|
|
91
|
+
if (this.adapter instanceof LocalExecutionAdapter) return this.adapter.getInterfaceInfo();
|
|
92
|
+
if (this.adapter instanceof RemoteExecutionAdapter) return this.adapter.getInterfaceInfo();
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
constructor(config){
|
|
96
|
+
_define_property(this, "adapter", void 0);
|
|
97
|
+
this.adapter = this.createAdapter(config.type, config.serverUrl, config.agent);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export { PlaygroundSDK };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk\\index.mjs","sources":["webpack://@sqaitech/playground/./src/sdk/index.ts"],"sourcesContent":["import type { DeviceAction } from '@sqaitech/core';\r\nimport { PLAYGROUND_SERVER_PORT } from '@sqaitech/shared/constants';\r\nimport type { BasePlaygroundAdapter } from '../adapters/base';\r\nimport { LocalExecutionAdapter } from '../adapters/local-execution';\r\nimport { RemoteExecutionAdapter } from '../adapters/remote-execution';\r\nimport type {\r\n ExecutionOptions,\r\n FormValue,\r\n PlaygroundAgent,\r\n PlaygroundConfig,\r\n ValidationResult,\r\n} from '../types';\r\n\r\nexport class PlaygroundSDK {\r\n private adapter: BasePlaygroundAdapter;\r\n\r\n constructor(config: PlaygroundConfig) {\r\n this.adapter = this.createAdapter(\r\n config.type,\r\n config.serverUrl,\r\n config.agent,\r\n );\r\n }\r\n\r\n private createAdapter(\r\n type: string,\r\n serverUrl?: string,\r\n agent?: PlaygroundAgent,\r\n ): BasePlaygroundAdapter {\r\n switch (type) {\r\n case 'local-execution':\r\n if (!agent) {\r\n throw new Error('Agent is required for local execution');\r\n }\r\n return new LocalExecutionAdapter(agent);\r\n case 'remote-execution': {\r\n // Use provided serverUrl first, then fallback to localhost if current page origin is file:// or default\r\n const finalServerUrl =\r\n serverUrl ||\r\n (typeof window !== 'undefined' &&\r\n window.location.protocol.includes('http')\r\n ? window.location.origin\r\n : `http://localhost:${PLAYGROUND_SERVER_PORT}`);\r\n\r\n return new RemoteExecutionAdapter(finalServerUrl);\r\n }\r\n default:\r\n throw new Error(`Unsupported execution type: ${type}`);\r\n }\r\n }\r\n\r\n async executeAction(\r\n actionType: string,\r\n value: FormValue,\r\n options: ExecutionOptions,\r\n ): Promise<unknown> {\r\n const result = await this.adapter.executeAction(actionType, value, options);\r\n\r\n // Stop any active polling for this request after execution completes\r\n if (options.requestId) {\r\n this.stopProgressPolling(options.requestId);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n async getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]> {\r\n // Both adapters now accept context parameter\r\n // Local will prioritize internal agent, Remote will use server + fallback\r\n return this.adapter.getActionSpace(context);\r\n }\r\n\r\n validateStructuredParams(\r\n value: FormValue,\r\n action: DeviceAction<unknown> | undefined,\r\n ): ValidationResult {\r\n return this.adapter.validateParams(value, action);\r\n }\r\n\r\n formatErrorMessage(error: any): string {\r\n return this.adapter.formatErrorMessage(error);\r\n }\r\n\r\n createDisplayContent(\r\n value: FormValue,\r\n needsStructuredParams: boolean,\r\n action: DeviceAction<unknown> | undefined,\r\n ): string {\r\n return this.adapter.createDisplayContent(\r\n value,\r\n needsStructuredParams,\r\n action,\r\n );\r\n }\r\n\r\n // Get adapter ID (works for both remote and local execution)\r\n get id(): string | undefined {\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n return this.adapter.id;\r\n }\r\n if (this.adapter instanceof LocalExecutionAdapter) {\r\n return this.adapter.id;\r\n }\r\n return undefined;\r\n }\r\n\r\n // Server communication methods (for remote execution)\r\n async checkStatus(): Promise<boolean> {\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n return this.adapter.checkStatus();\r\n }\r\n return true; // For local execution, always return true\r\n }\r\n\r\n async overrideConfig(aiConfig: any): Promise<void> {\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n return this.adapter.overrideConfig(aiConfig);\r\n }\r\n // For local execution, this is a no-op\r\n }\r\n\r\n async getTaskProgress(requestId: string): Promise<{ tip?: string }> {\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n return this.adapter.getTaskProgress(requestId);\r\n }\r\n if (this.adapter instanceof LocalExecutionAdapter) {\r\n return this.adapter.getTaskProgress(requestId);\r\n }\r\n return { tip: undefined }; // Fallback\r\n }\r\n\r\n // Cancel task (for remote execution)\r\n async cancelTask(requestId: string): Promise<any> {\r\n // Stop progress polling for this request\r\n this.stopProgressPolling(requestId);\r\n\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n return this.adapter.cancelTask(requestId);\r\n }\r\n return { error: 'Cancel task not supported in local execution mode' };\r\n }\r\n\r\n // Progress callback management\r\n onProgressUpdate(callback: (tip: string) => void): void {\r\n // Pass the callback to the adapter if it supports it\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n this.adapter.setProgressCallback(callback);\r\n } else if (this.adapter instanceof LocalExecutionAdapter) {\r\n this.adapter.setProgressCallback(callback);\r\n }\r\n }\r\n\r\n // Start progress polling for remote execution (deprecated - now handled by adapter)\r\n startProgressPolling(requestId: string): void {\r\n // This method is now handled by the RemoteExecutionAdapter automatically\r\n // when executeAction is called with a requestId\r\n console.warn(\r\n 'startProgressPolling is deprecated - polling is now automatic',\r\n );\r\n }\r\n\r\n // Stop progress polling for a specific request (deprecated - now handled by adapter)\r\n stopProgressPolling(requestId: string): void {\r\n // This method is now handled by the RemoteExecutionAdapter automatically\r\n console.warn(\r\n 'stopProgressPolling is deprecated - polling cleanup is now automatic',\r\n );\r\n }\r\n\r\n // Cancel execution - supports both remote and local\r\n async cancelExecution(requestId: string): Promise<void> {\r\n this.stopProgressPolling(requestId);\r\n\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n await this.adapter.cancelTask(requestId);\r\n } else if (this.adapter instanceof LocalExecutionAdapter) {\r\n // For local execution, we might need to implement agent cancellation\r\n console.warn('Local execution cancellation not fully implemented');\r\n }\r\n }\r\n\r\n // Screenshot method for remote execution\r\n async getScreenshot(): Promise<{\r\n screenshot: string;\r\n timestamp: number;\r\n } | null> {\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n return this.adapter.getScreenshot();\r\n }\r\n return null; // For local execution, not supported yet\r\n }\r\n\r\n // Get interface information (type and description)\r\n async getInterfaceInfo(): Promise<{\r\n type: string;\r\n description?: string;\r\n } | null> {\r\n if (this.adapter instanceof LocalExecutionAdapter) {\r\n return this.adapter.getInterfaceInfo();\r\n }\r\n if (this.adapter instanceof RemoteExecutionAdapter) {\r\n return this.adapter.getInterfaceInfo();\r\n }\r\n return null;\r\n }\r\n}\r\n"],"names":["PlaygroundSDK","type","serverUrl","agent","Error","LocalExecutionAdapter","finalServerUrl","window","PLAYGROUND_SERVER_PORT","RemoteExecutionAdapter","actionType","value","options","result","context","action","error","needsStructuredParams","aiConfig","requestId","undefined","callback","console","config"],"mappings":"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"}
|