@sqaitech/playground 0.30.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/es/adapters/base.mjs +131 -0
  2. package/dist/es/adapters/base.mjs.map +1 -0
  3. package/dist/es/adapters/local-execution.mjs +140 -0
  4. package/dist/es/adapters/local-execution.mjs.map +1 -0
  5. package/dist/es/adapters/remote-execution.mjs +308 -0
  6. package/dist/es/adapters/remote-execution.mjs.map +1 -0
  7. package/dist/es/common.mjs +148 -0
  8. package/dist/es/common.mjs.map +1 -0
  9. package/dist/es/index.browser.mjs +9 -0
  10. package/dist/es/index.browser.mjs.map +1 -0
  11. package/dist/es/index.mjs +8 -0
  12. package/dist/es/launcher.mjs +95 -0
  13. package/dist/es/launcher.mjs.map +1 -0
  14. package/dist/es/sdk/index.mjs +102 -0
  15. package/dist/es/sdk/index.mjs.map +1 -0
  16. package/dist/es/server.mjs +385 -0
  17. package/dist/es/server.mjs.map +1 -0
  18. package/dist/es/types.mjs +0 -0
  19. package/dist/lib/adapters/base.js +165 -0
  20. package/dist/lib/adapters/base.js.map +1 -0
  21. package/dist/lib/adapters/local-execution.js +174 -0
  22. package/dist/lib/adapters/local-execution.js.map +1 -0
  23. package/dist/lib/adapters/remote-execution.js +342 -0
  24. package/dist/lib/adapters/remote-execution.js.map +1 -0
  25. package/dist/lib/common.js +200 -0
  26. package/dist/lib/common.js.map +1 -0
  27. package/dist/lib/index.browser.js +73 -0
  28. package/dist/lib/index.browser.js.map +1 -0
  29. package/dist/lib/index.js +77 -0
  30. package/dist/lib/index.js.map +1 -0
  31. package/dist/lib/launcher.js +140 -0
  32. package/dist/lib/launcher.js.map +1 -0
  33. package/dist/lib/sdk/index.js +136 -0
  34. package/dist/lib/sdk/index.js.map +1 -0
  35. package/dist/lib/server.js +435 -0
  36. package/dist/lib/server.js.map +1 -0
  37. package/dist/lib/types.js +20 -0
  38. package/dist/lib/types.js.map +1 -0
  39. package/dist/types/adapters/base.d.ts +20 -0
  40. package/dist/types/adapters/local-execution.d.ts +31 -0
  41. package/dist/types/adapters/remote-execution.d.ts +38 -0
  42. package/dist/types/common.d.ts +9 -0
  43. package/dist/types/index.browser.d.ts +7 -0
  44. package/dist/types/index.d.ts +9 -0
  45. package/dist/types/launcher.d.ts +97 -0
  46. package/dist/types/sdk/index.d.ts +31 -0
  47. package/dist/types/server.d.ts +75 -0
  48. package/dist/types/types.d.ts +49 -0
  49. package/package.json +51 -0
  50. package/static/favicon.ico +0 -0
  51. package/static/index.html +1 -0
  52. package/static/static/css/index.60c69390.css +2 -0
  53. package/static/static/css/index.60c69390.css.map +1 -0
  54. package/static/static/js/931.dc961e99.js +620 -0
  55. package/static/static/js/931.dc961e99.js.LICENSE.txt +146 -0
  56. package/static/static/js/931.dc961e99.js.map +1 -0
  57. package/static/static/js/async/173.9cf6b074.js +3 -0
  58. package/static/static/js/async/173.9cf6b074.js.map +1 -0
  59. package/static/static/js/async/212.e243c338.js +158 -0
  60. package/static/static/js/async/212.e243c338.js.map +1 -0
  61. package/static/static/js/async/329.f888b505.js +26 -0
  62. package/static/static/js/async/329.f888b505.js.map +1 -0
  63. package/static/static/js/async/364.1821e74b.js +30 -0
  64. package/static/static/js/async/364.1821e74b.js.map +1 -0
  65. package/static/static/js/async/544.b73fa603.js +2 -0
  66. package/static/static/js/async/544.b73fa603.js.map +1 -0
  67. package/static/static/js/async/582.5dccae2d.js +21 -0
  68. package/static/static/js/async/582.5dccae2d.js.map +1 -0
  69. package/static/static/js/async/624.45ee2b2c.js +3 -0
  70. package/static/static/js/async/624.45ee2b2c.js.map +1 -0
  71. package/static/static/js/async/644.6bdc4065.js +1 -0
  72. package/static/static/js/async/659.9afd03db.js +21 -0
  73. package/static/static/js/async/659.9afd03db.js.map +1 -0
  74. package/static/static/js/async/702.60261735.js +231 -0
  75. package/static/static/js/async/702.60261735.js.map +1 -0
  76. package/static/static/js/async/920.7d9a9aa8.js +2 -0
  77. package/static/static/js/async/920.7d9a9aa8.js.map +1 -0
  78. package/static/static/js/async/983.8b91303f.js +1 -0
  79. package/static/static/js/index.5cccbdaf.js +10 -0
  80. package/static/static/js/index.5cccbdaf.js.LICENSE.txt +7 -0
  81. package/static/static/js/index.5cccbdaf.js.map +1 -0
  82. package/static/static/js/index.8a10896b.js +10 -0
  83. package/static/static/js/index.8a10896b.js.LICENSE.txt +7 -0
  84. package/static/static/js/index.8a10896b.js.map +1 -0
  85. package/static/static/js/index.f21bb1df.js +10 -0
  86. package/static/static/js/index.f21bb1df.js.LICENSE.txt +7 -0
  87. package/static/static/js/index.f21bb1df.js.map +1 -0
  88. package/static/static/js/lib-react.f566a9ed.js +3 -0
  89. package/static/static/js/lib-react.f566a9ed.js.LICENSE.txt +39 -0
  90. package/static/static/js/lib-react.f566a9ed.js.map +1 -0
  91. package/static/static/svg/server-offline-foreground.3113df3c.svg +36 -0
  92. package/static/static/wasm/9e906fbf55e08f98.module.wasm +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sources":["webpack://@sqaitech/playground/webpack/runtime/compat_get_default_export","webpack://@sqaitech/playground/webpack/runtime/define_property_getters","webpack://@sqaitech/playground/webpack/runtime/has_own_property","webpack://@sqaitech/playground/webpack/runtime/make_namespace_object","webpack://@sqaitech/playground/./src/server.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__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 { existsSync, readFileSync, writeFileSync } from 'node:fs';\r\nimport type { Server } from 'node:http';\r\nimport { dirname, join } from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\nimport type { Agent as PageAgent } from '@sqaitech/core/agent';\r\nimport { getTmpDir } from '@sqaitech/core/utils';\r\nimport { PLAYGROUND_SERVER_PORT } from '@sqaitech/shared/constants';\r\nimport { overrideAIConfig } from '@sqaitech/shared/env';\r\nimport { uuid } from '@sqaitech/shared/utils';\r\nimport express, { type Request, type Response } from 'express';\r\nimport { executeAction, formatErrorMessage } from './common';\r\n\r\nimport 'dotenv/config';\r\n\r\nconst defaultPort = PLAYGROUND_SERVER_PORT;\r\n\r\n// Static path for playground files\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = dirname(__filename);\r\nconst STATIC_PATH = join(__dirname, '..', '..', 'static');\r\n\r\nconst errorHandler = (\r\n err: unknown,\r\n req: Request,\r\n res: Response,\r\n next: express.NextFunction,\r\n) => {\r\n console.error(err);\r\n const errorMessage =\r\n err instanceof Error ? err.message : 'Internal server error';\r\n res.status(500).json({\r\n error: errorMessage,\r\n });\r\n};\r\n\r\nclass PlaygroundServer {\r\n private _app: express.Application;\r\n tmpDir: string;\r\n server?: Server;\r\n port?: number | null;\r\n agent: PageAgent;\r\n staticPath: string;\r\n taskProgressTips: Record<string, string>;\r\n id: string; // Unique identifier for this server instance\r\n\r\n private _initialized = false;\r\n\r\n // Factory function for recreating agent\r\n private agentFactory?: (() => PageAgent | Promise<PageAgent>) | null;\r\n\r\n // Track current running task\r\n private currentTaskId: string | null = null;\r\n\r\n constructor(\r\n agent: PageAgent | (() => PageAgent) | (() => Promise<PageAgent>),\r\n staticPath = STATIC_PATH,\r\n id?: string, // Optional override ID\r\n ) {\r\n this._app = express();\r\n this.tmpDir = getTmpDir()!;\r\n this.staticPath = staticPath;\r\n this.taskProgressTips = {};\r\n // Use provided ID, or generate random UUID for each startup\r\n this.id = id || uuid();\r\n\r\n // Support both instance and factory function modes\r\n if (typeof agent === 'function') {\r\n this.agentFactory = agent;\r\n this.agent = null as any; // Will be initialized in launch()\r\n } else {\r\n this.agent = agent;\r\n this.agentFactory = null;\r\n }\r\n }\r\n\r\n /**\r\n * Get the Express app instance for custom configuration\r\n *\r\n * IMPORTANT: Add middleware (like CORS) BEFORE calling launch()\r\n * The routes are initialized when launch() is called, so middleware\r\n * added after launch() will not affect the API routes.\r\n *\r\n * @example\r\n * ```typescript\r\n * import cors from 'cors';\r\n *\r\n * const server = new PlaygroundServer(agent);\r\n *\r\n * // Add CORS middleware before launch\r\n * server.app.use(cors({\r\n * origin: true,\r\n * credentials: true,\r\n * methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']\r\n * }));\r\n *\r\n * await server.launch();\r\n * ```\r\n */\r\n get app(): express.Application {\r\n return this._app;\r\n }\r\n\r\n /**\r\n * Initialize Express app with all routes and middleware\r\n * Called automatically by launch() if not already initialized\r\n */\r\n private initializeApp(): void {\r\n if (this._initialized) return;\r\n\r\n // Built-in middleware to parse JSON bodies\r\n this._app.use(express.json({ limit: '50mb' }));\r\n\r\n // Context update middleware (after JSON parsing)\r\n this._app.use(\r\n (req: Request, _res: Response, next: express.NextFunction) => {\r\n const { context } = req.body || {};\r\n if (\r\n context &&\r\n 'updateContext' in this.agent.interface &&\r\n typeof this.agent.interface.updateContext === 'function'\r\n ) {\r\n this.agent.interface.updateContext(context);\r\n console.log('Context updated by PlaygroundServer middleware');\r\n }\r\n next();\r\n },\r\n );\r\n\r\n // NOTE: CORS middleware should be added externally via server.app.use()\r\n // before calling server.launch() if needed\r\n\r\n // API routes\r\n this.setupRoutes();\r\n\r\n // Static file serving (if staticPath is provided)\r\n this.setupStaticRoutes();\r\n\r\n // Error handler middleware (must be last)\r\n this._app.use(errorHandler);\r\n\r\n this._initialized = true;\r\n }\r\n\r\n filePathForUuid(uuid: string) {\r\n return join(this.tmpDir, `${uuid}.json`);\r\n }\r\n\r\n saveContextFile(uuid: string, context: string) {\r\n const tmpFile = this.filePathForUuid(uuid);\r\n console.log(`save context file: ${tmpFile}`);\r\n writeFileSync(tmpFile, context);\r\n return tmpFile;\r\n }\r\n\r\n /**\r\n * Recreate agent instance (for cancellation)\r\n */\r\n private async recreateAgent(): Promise<void> {\r\n if (!this.agentFactory) {\r\n console.warn(\r\n 'Cannot recreate agent: factory function not provided. Agent recreation is only available when using factory mode.',\r\n );\r\n return;\r\n }\r\n\r\n console.log('Recreating agent to cancel current task...');\r\n\r\n // Destroy old agent instance\r\n try {\r\n if (this.agent && typeof this.agent.destroy === 'function') {\r\n await this.agent.destroy();\r\n }\r\n } catch (error) {\r\n console.warn('Failed to destroy old agent:', error);\r\n }\r\n\r\n // Create new agent instance\r\n try {\r\n this.agent = await this.agentFactory();\r\n console.log('Agent recreated successfully');\r\n } catch (error) {\r\n console.error('Failed to recreate agent:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Setup all API routes\r\n */\r\n private setupRoutes(): void {\r\n this._app.get('/status', async (req: Request, res: Response) => {\r\n res.send({\r\n status: 'ok',\r\n id: this.id,\r\n });\r\n });\r\n\r\n this._app.get('/context/:uuid', async (req: Request, res: Response) => {\r\n const { uuid } = req.params;\r\n const contextFile = this.filePathForUuid(uuid);\r\n\r\n if (!existsSync(contextFile)) {\r\n return res.status(404).json({\r\n error: 'Context not found',\r\n });\r\n }\r\n\r\n const context = readFileSync(contextFile, 'utf8');\r\n res.json({\r\n context,\r\n });\r\n });\r\n\r\n this._app.get(\r\n '/task-progress/:requestId',\r\n async (req: Request, res: Response) => {\r\n const { requestId } = req.params;\r\n res.json({\r\n tip: this.taskProgressTips[requestId] || '',\r\n });\r\n },\r\n );\r\n\r\n this._app.post('/action-space', async (req: Request, res: Response) => {\r\n try {\r\n let actionSpace = [];\r\n\r\n actionSpace = await this.agent.interface.actionSpace();\r\n\r\n // Process actionSpace to make paramSchema serializable with shape info\r\n const processedActionSpace = actionSpace.map((action: unknown) => {\r\n if (action && typeof action === 'object' && 'paramSchema' in action) {\r\n const typedAction = action as {\r\n paramSchema?: { shape?: object; [key: string]: unknown };\r\n [key: string]: unknown;\r\n };\r\n if (\r\n typedAction.paramSchema &&\r\n typeof typedAction.paramSchema === 'object'\r\n ) {\r\n // Extract shape information from Zod schema\r\n let processedSchema = null;\r\n\r\n try {\r\n // Extract shape from runtime Zod object\r\n if (\r\n typedAction.paramSchema.shape &&\r\n typeof typedAction.paramSchema.shape === 'object'\r\n ) {\r\n processedSchema = {\r\n type: 'ZodObject',\r\n shape: typedAction.paramSchema.shape,\r\n };\r\n }\r\n } catch (e) {\r\n const actionName =\r\n 'name' in typedAction && typeof typedAction.name === 'string'\r\n ? typedAction.name\r\n : 'unknown';\r\n console.warn(\r\n 'Failed to process paramSchema for action:',\r\n actionName,\r\n e,\r\n );\r\n }\r\n\r\n return {\r\n ...typedAction,\r\n paramSchema: processedSchema,\r\n };\r\n }\r\n }\r\n return action;\r\n });\r\n\r\n res.json(processedActionSpace);\r\n } catch (error: unknown) {\r\n const errorMessage =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n console.error('Failed to get action space:', error);\r\n res.status(500).json({\r\n error: errorMessage,\r\n });\r\n }\r\n });\r\n\r\n // -------------------------\r\n // actions from report file\r\n this._app.post(\r\n '/playground-with-context',\r\n async (req: Request, res: Response) => {\r\n const context = req.body.context;\r\n\r\n if (!context) {\r\n return res.status(400).json({\r\n error: 'context is required',\r\n });\r\n }\r\n\r\n const requestId = uuid();\r\n this.saveContextFile(requestId, context);\r\n return res.json({\r\n location: `/playground/${requestId}`,\r\n uuid: requestId,\r\n });\r\n },\r\n );\r\n\r\n this._app.post('/execute', async (req: Request, res: Response) => {\r\n const {\r\n type,\r\n prompt,\r\n params,\r\n requestId,\r\n deepThink,\r\n screenshotIncluded,\r\n domIncluded,\r\n } = req.body;\r\n\r\n if (!type) {\r\n return res.status(400).json({\r\n error: 'type is required',\r\n });\r\n }\r\n\r\n // Check if another task is running\r\n if (this.currentTaskId) {\r\n return res.status(409).json({\r\n error: 'Another task is already running',\r\n currentTaskId: this.currentTaskId,\r\n });\r\n }\r\n\r\n // Lock this task\r\n if (requestId) {\r\n this.currentTaskId = requestId;\r\n this.taskProgressTips[requestId] = '';\r\n\r\n this.agent.onTaskStartTip = (tip: string) => {\r\n this.taskProgressTips[requestId] = tip;\r\n };\r\n }\r\n\r\n const response: {\r\n result: unknown;\r\n dump: string | null;\r\n error: string | null;\r\n reportHTML: string | null;\r\n requestId?: string;\r\n } = {\r\n result: null,\r\n dump: null,\r\n error: null,\r\n reportHTML: null,\r\n requestId,\r\n };\r\n\r\n const startTime = Date.now();\r\n try {\r\n // Get action space to check for dynamic actions\r\n const actionSpace = await this.agent.interface.actionSpace();\r\n\r\n // Prepare value object for executeAction\r\n const value = {\r\n type,\r\n prompt,\r\n params,\r\n };\r\n\r\n response.result = await executeAction(\r\n this.agent,\r\n type,\r\n actionSpace,\r\n value,\r\n {\r\n deepThink,\r\n screenshotIncluded,\r\n domIncluded,\r\n },\r\n );\r\n } catch (error: unknown) {\r\n response.error = formatErrorMessage(error);\r\n }\r\n\r\n try {\r\n response.dump = JSON.parse(this.agent.dumpDataString());\r\n response.reportHTML = this.agent.reportHTMLString() || null;\r\n\r\n this.agent.writeOutActionDumps();\r\n this.agent.resetDump();\r\n } catch (error: unknown) {\r\n const errorMessage =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n console.error(\r\n `write out dump failed: requestId: ${requestId}, ${errorMessage}`,\r\n );\r\n }\r\n\r\n res.send(response);\r\n const timeCost = Date.now() - startTime;\r\n\r\n if (response.error) {\r\n console.error(\r\n `handle request failed after ${timeCost}ms: requestId: ${requestId}, ${response.error}`,\r\n );\r\n } else {\r\n console.log(\r\n `handle request done after ${timeCost}ms: requestId: ${requestId}`,\r\n );\r\n }\r\n\r\n // Clean up task progress tip and unlock after execution completes\r\n if (requestId) {\r\n delete this.taskProgressTips[requestId];\r\n // Release the lock\r\n if (this.currentTaskId === requestId) {\r\n this.currentTaskId = null;\r\n }\r\n }\r\n });\r\n\r\n this._app.post(\r\n '/cancel/:requestId',\r\n async (req: Request, res: Response) => {\r\n const { requestId } = req.params;\r\n\r\n if (!requestId) {\r\n return res.status(400).json({\r\n error: 'requestId is required',\r\n });\r\n }\r\n\r\n try {\r\n // Check if this is the current running task\r\n if (this.currentTaskId !== requestId) {\r\n return res.json({\r\n status: 'not_found',\r\n message: 'Task not found or already completed',\r\n });\r\n }\r\n\r\n console.log(`Cancelling task: ${requestId}`);\r\n\r\n // Recreate agent to cancel the current task\r\n await this.recreateAgent();\r\n\r\n // Clean up\r\n delete this.taskProgressTips[requestId];\r\n this.currentTaskId = null;\r\n\r\n res.json({\r\n status: 'cancelled',\r\n message: 'Task cancelled successfully by recreating agent',\r\n });\r\n } catch (error: unknown) {\r\n const errorMessage =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to cancel: ${errorMessage}`);\r\n res.status(500).json({\r\n error: `Failed to cancel: ${errorMessage}`,\r\n });\r\n }\r\n },\r\n );\r\n\r\n // Screenshot API for real-time screenshot polling\r\n this._app.get('/screenshot', async (_req: Request, res: Response) => {\r\n try {\r\n // Check if page has screenshotBase64 method\r\n if (typeof this.agent.interface.screenshotBase64 !== 'function') {\r\n return res.status(500).json({\r\n error: 'Screenshot method not available on current interface',\r\n });\r\n }\r\n\r\n const base64Screenshot = await this.agent.interface.screenshotBase64();\r\n\r\n res.json({\r\n screenshot: base64Screenshot,\r\n timestamp: Date.now(),\r\n });\r\n } catch (error: unknown) {\r\n const errorMessage =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to take screenshot: ${errorMessage}`);\r\n res.status(500).json({\r\n error: `Failed to take screenshot: ${errorMessage}`,\r\n });\r\n }\r\n });\r\n\r\n // Interface info API for getting interface type and description\r\n this._app.get('/interface-info', async (_req: Request, res: Response) => {\r\n try {\r\n const type = this.agent.interface.interfaceType || 'Unknown';\r\n const description = this.agent.interface.describe?.() || undefined;\r\n\r\n res.json({\r\n type,\r\n description,\r\n });\r\n } catch (error: unknown) {\r\n const errorMessage =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to get interface info: ${errorMessage}`);\r\n res.status(500).json({\r\n error: `Failed to get interface info: ${errorMessage}`,\r\n });\r\n }\r\n });\r\n\r\n this.app.post('/config', async (req: Request, res: Response) => {\r\n const { aiConfig } = req.body;\r\n\r\n if (!aiConfig || typeof aiConfig !== 'object') {\r\n return res.status(400).json({\r\n error: 'aiConfig is required and must be an object',\r\n });\r\n }\r\n\r\n if (Object.keys(aiConfig).length === 0) {\r\n return res.json({\r\n status: 'ok',\r\n message: 'AI config not changed due to empty object',\r\n });\r\n }\r\n\r\n try {\r\n overrideAIConfig(aiConfig);\r\n\r\n return res.json({\r\n status: 'ok',\r\n message: 'AI config updated successfully',\r\n });\r\n } catch (error: unknown) {\r\n const errorMessage =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to update AI config: ${errorMessage}`);\r\n return res.status(500).json({\r\n error: `Failed to update AI config: ${errorMessage}`,\r\n });\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Setup static file serving routes\r\n */\r\n private setupStaticRoutes(): void {\r\n // Handle index.html with port injection\r\n this._app.get('/', (_req: Request, res: Response) => {\r\n this.serveHtmlWithPorts(res);\r\n });\r\n\r\n this._app.get('/index.html', (_req: Request, res: Response) => {\r\n this.serveHtmlWithPorts(res);\r\n });\r\n\r\n // Use express.static middleware for secure static file serving\r\n this._app.use(express.static(this.staticPath));\r\n\r\n // Fallback to index.html for SPA routing\r\n this._app.get('*', (_req: Request, res: Response) => {\r\n this.serveHtmlWithPorts(res);\r\n });\r\n }\r\n\r\n /**\r\n * Serve HTML with injected port configuration\r\n */\r\n private serveHtmlWithPorts(res: Response): void {\r\n try {\r\n const htmlPath = join(this.staticPath, 'index.html');\r\n let html = readFileSync(htmlPath, 'utf8');\r\n\r\n // Get scrcpy server port from global\r\n const scrcpyPort = (global as any).scrcpyServerPort || this.port! + 1;\r\n\r\n // Inject scrcpy port configuration script into HTML head\r\n const configScript = `\r\n <script>\r\n window.SCRCPY_PORT = ${scrcpyPort};\r\n </script>\r\n `;\r\n\r\n // Insert the script before closing </head> tag\r\n html = html.replace('</head>', `${configScript}</head>`);\r\n\r\n res.setHeader('Content-Type', 'text/html');\r\n res.send(html);\r\n } catch (error) {\r\n console.error('Error serving HTML with ports:', error);\r\n res.status(500).send('Internal Server Error');\r\n }\r\n }\r\n\r\n /**\r\n * Launch the server on specified port\r\n */\r\n async launch(port?: number): Promise<PlaygroundServer> {\r\n // If using factory mode, initialize agent\r\n if (this.agentFactory) {\r\n console.log('Initializing agent from factory function...');\r\n this.agent = await this.agentFactory();\r\n console.log('Agent initialized successfully');\r\n }\r\n\r\n // Initialize routes now, after any middleware has been added\r\n this.initializeApp();\r\n\r\n this.port = port || defaultPort;\r\n\r\n return new Promise((resolve) => {\r\n const serverPort = this.port;\r\n this.server = this._app.listen(serverPort, () => {\r\n resolve(this);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Close the server and clean up resources\r\n */\r\n async close(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n if (this.server) {\r\n // Clean up the single agent\r\n try {\r\n this.agent.destroy();\r\n } catch (error) {\r\n console.warn('Failed to destroy agent:', error);\r\n }\r\n this.taskProgressTips = {};\r\n\r\n // Close the server\r\n this.server.close((error) => {\r\n if (error) {\r\n reject(error);\r\n } else {\r\n this.server = undefined;\r\n resolve();\r\n }\r\n });\r\n } else {\r\n resolve();\r\n }\r\n });\r\n }\r\n}\r\n\r\nexport default PlaygroundServer;\r\nexport { PlaygroundServer };\r\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","defaultPort","PLAYGROUND_SERVER_PORT","__filename","fileURLToPath","__dirname","dirname","STATIC_PATH","join","errorHandler","err","req","res","next","console","errorMessage","Error","PlaygroundServer","express","_res","context","uuid","tmpFile","writeFileSync","error","contextFile","existsSync","readFileSync","requestId","actionSpace","processedActionSpace","action","typedAction","processedSchema","e","actionName","type","prompt","params","deepThink","screenshotIncluded","domIncluded","tip","response","startTime","Date","value","executeAction","formatErrorMessage","JSON","timeCost","_req","base64Screenshot","_this_agent_interface","description","undefined","aiConfig","overrideAIConfig","htmlPath","html","scrcpyPort","global","configScript","port","Promise","resolve","serverPort","reject","agent","staticPath","id","getTmpDir"],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.r = (exports1)=>{
5
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
6
+ value: 'Module'
7
+ });
8
+ Object.defineProperty(exports1, '__esModule', {
9
+ value: true
10
+ });
11
+ };
12
+ })();
13
+ var __webpack_exports__ = {};
14
+ __webpack_require__.r(__webpack_exports__);
15
+ for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
16
+ Object.defineProperty(exports, '__esModule', {
17
+ value: true
18
+ });
19
+
20
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":["webpack://@sqaitech/playground/webpack/runtime/make_namespace_object"],"sourcesContent":["// 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};"],"names":["__webpack_require__","Symbol","Object"],"mappings":";;;IACAA,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOC,UAA0BA,OAAO,WAAW,EACrDC,OAAO,cAAc,CAAC,UAASD,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEC,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D"}
@@ -0,0 +1,20 @@
1
+ import type { DeviceAction } from '@sqaitech/core';
2
+ import type { ExecutionOptions, FormValue, ValidationResult } from '../types';
3
+ export declare abstract class BasePlaygroundAdapter {
4
+ abstract parseStructuredParams(action: DeviceAction<unknown>, params: Record<string, unknown>, options: ExecutionOptions): Promise<unknown[]>;
5
+ abstract formatErrorMessage(error: any): string;
6
+ abstract executeAction(actionType: string, value: FormValue, options: ExecutionOptions): Promise<unknown>;
7
+ getActionSpace(_context: any): Promise<DeviceAction<unknown>[]>;
8
+ validateParams(value: FormValue, action: DeviceAction<unknown> | undefined): ValidationResult;
9
+ createDisplayContent(value: FormValue, needsStructuredParams: boolean, action: DeviceAction<unknown> | undefined): string;
10
+ protected formatBasicErrorMessage(error: any): string;
11
+ protected getSchemaKeys(action: DeviceAction<unknown>): string[];
12
+ protected filterValidParams(params: Record<string, unknown>, excludeKeys?: string[]): Record<string, unknown>;
13
+ protected actionNeedsStructuredParams(action: DeviceAction<unknown>): boolean;
14
+ protected prepareParamsForValidation(params: Record<string, unknown>, action: DeviceAction<unknown>): Record<string, unknown>;
15
+ protected handleValidationError(error: unknown): ValidationResult;
16
+ protected buildParamsDisplayList(params: Record<string, unknown>, action: DeviceAction<unknown>): string[];
17
+ protected isValidParamValue(value: unknown): boolean;
18
+ protected capitalizeFirstLetter(str: string): string;
19
+ protected formatParamValue(key: string, value: unknown, isLocateField: boolean): string;
20
+ }
@@ -0,0 +1,31 @@
1
+ import type { DeviceAction } from '@sqaitech/core';
2
+ import type { ExecutionOptions, FormValue, PlaygroundAgent } from '../types';
3
+ import { BasePlaygroundAdapter } from './base';
4
+ export declare class LocalExecutionAdapter extends BasePlaygroundAdapter {
5
+ private agent;
6
+ private taskProgressTips;
7
+ private progressCallback?;
8
+ private readonly _id;
9
+ private currentRequestId?;
10
+ constructor(agent: PlaygroundAgent);
11
+ get id(): string;
12
+ setProgressCallback(callback: (tip: string) => void): void;
13
+ private cleanup;
14
+ parseStructuredParams(action: DeviceAction<unknown>, params: Record<string, unknown>, options: ExecutionOptions): Promise<unknown[]>;
15
+ formatErrorMessage(error: any): string;
16
+ getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]>;
17
+ checkStatus(): Promise<boolean>;
18
+ overrideConfig(aiConfig: Record<string, unknown>): Promise<void>;
19
+ executeAction(actionType: string, value: FormValue, options: ExecutionOptions): Promise<unknown>;
20
+ getTaskProgress(requestId: string): Promise<{
21
+ tip?: string;
22
+ }>;
23
+ cancelTask(_requestId: string): Promise<{
24
+ error?: string;
25
+ success?: boolean;
26
+ }>;
27
+ getInterfaceInfo(): Promise<{
28
+ type: string;
29
+ description?: string;
30
+ } | null>;
31
+ }
@@ -0,0 +1,38 @@
1
+ import type { DeviceAction } from '@sqaitech/core';
2
+ import type { ExecutionOptions, FormValue, ValidationResult } from '../types';
3
+ import { BasePlaygroundAdapter } from './base';
4
+ export declare class RemoteExecutionAdapter extends BasePlaygroundAdapter {
5
+ private serverUrl?;
6
+ private progressPolling;
7
+ private progressCallback?;
8
+ private _id?;
9
+ constructor(serverUrl: string);
10
+ get id(): string | undefined;
11
+ validateParams(value: FormValue, action: DeviceAction<unknown> | undefined): ValidationResult;
12
+ parseStructuredParams(action: DeviceAction<unknown>, params: Record<string, unknown>, options: ExecutionOptions): Promise<unknown[]>;
13
+ formatErrorMessage(error: any): string;
14
+ executeAction(actionType: string, value: FormValue, options: ExecutionOptions): Promise<unknown>;
15
+ private executeViaServer;
16
+ private buildOptionalPayloadParams;
17
+ getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]>;
18
+ checkStatus(): Promise<boolean>;
19
+ overrideConfig(aiConfig: Record<string, unknown>): Promise<void>;
20
+ getTaskProgress(requestId: string): Promise<{
21
+ tip?: string;
22
+ }>;
23
+ cancelTask(requestId: string): Promise<{
24
+ error?: string;
25
+ success?: boolean;
26
+ }>;
27
+ setProgressCallback(callback: (tip: string) => void): void;
28
+ private startProgressPolling;
29
+ private stopProgressPolling;
30
+ getScreenshot(): Promise<{
31
+ screenshot: string;
32
+ timestamp: number;
33
+ } | null>;
34
+ getInterfaceInfo(): Promise<{
35
+ type: string;
36
+ description?: string;
37
+ } | null>;
38
+ }
@@ -0,0 +1,9 @@
1
+ import type { DeviceAction } from '@sqaitech/core';
2
+ import type { ExecutionOptions, FormValue, PlaygroundAgent, ValidationResult } from './types';
3
+ export declare const dataExtractionAPIs: string[];
4
+ export declare const validationAPIs: string[];
5
+ export declare const noReplayAPIs: string[];
6
+ export declare const formatErrorMessage: (e: any) => string;
7
+ export declare function parseStructuredParams(action: DeviceAction<unknown>, params: Record<string, unknown>, options?: ExecutionOptions): Promise<unknown[]>;
8
+ export declare function validateStructuredParams(value: FormValue, action: DeviceAction<unknown> | undefined): ValidationResult;
9
+ export declare function executeAction(activeAgent: PlaygroundAgent, actionType: string, actionSpace: DeviceAction<unknown>[], value: FormValue, options: ExecutionOptions): Promise<unknown>;
@@ -0,0 +1,7 @@
1
+ export { dataExtractionAPIs, noReplayAPIs, validationAPIs, formatErrorMessage, validateStructuredParams, executeAction, } from './common';
2
+ export { PlaygroundSDK } from './sdk';
3
+ export { BasePlaygroundAdapter } from './adapters/base';
4
+ export { LocalExecutionAdapter } from './adapters/local-execution';
5
+ export { RemoteExecutionAdapter } from './adapters/remote-execution';
6
+ export declare const PlaygroundServer: undefined;
7
+ export type { ExecutionOptions, FormValue, PlaygroundAgent, ValidationResult, PlaygroundConfig, ExecutionType, PlaygroundAdapter, } from './types';
@@ -0,0 +1,9 @@
1
+ export { dataExtractionAPIs, noReplayAPIs, validationAPIs, formatErrorMessage, validateStructuredParams, executeAction, } from './common';
2
+ export { PlaygroundServer } from './server';
3
+ export { playgroundForAgent } from './launcher';
4
+ export { PlaygroundSDK } from './sdk';
5
+ export { BasePlaygroundAdapter } from './adapters/base';
6
+ export { LocalExecutionAdapter } from './adapters/local-execution';
7
+ export { RemoteExecutionAdapter } from './adapters/remote-execution';
8
+ export type { ExecutionOptions, FormValue, PlaygroundAgent, ValidationResult, PlaygroundConfig, ExecutionType, PlaygroundAdapter, ServerResponse, } from './types';
9
+ export type { LaunchPlaygroundOptions, LaunchPlaygroundResult, } from './launcher';
@@ -0,0 +1,97 @@
1
+ import type { Agent } from '@sqaitech/core/agent';
2
+ import PlaygroundServer from './server';
3
+ export interface LaunchPlaygroundOptions {
4
+ /**
5
+ * Port to start the playground server on
6
+ * @default 5800
7
+ */
8
+ port?: number;
9
+ /**
10
+ * Whether to automatically open the playground in browser
11
+ * @default true
12
+ */
13
+ openBrowser?: boolean;
14
+ /**
15
+ * Custom browser command to open playground
16
+ * @default 'open' on macOS, 'start' on Windows, 'xdg-open' on Linux
17
+ */
18
+ browserCommand?: string;
19
+ /**
20
+ * Whether to show server logs
21
+ * @default true
22
+ */
23
+ verbose?: boolean;
24
+ /**
25
+ * Fixed ID for the playground server instance
26
+ * If provided, the same ID will be used across restarts,
27
+ * allowing chat history to persist
28
+ * @default undefined (generates random UUID)
29
+ */
30
+ id?: string;
31
+ /**
32
+ * Whether to enable CORS (Cross-Origin Resource Sharing)
33
+ * @default false
34
+ */
35
+ enableCors?: boolean;
36
+ /**
37
+ * CORS configuration options
38
+ * @default { origin: '*', credentials: true } when enableCors is true
39
+ */
40
+ corsOptions?: {
41
+ origin?: string | boolean | string[];
42
+ credentials?: boolean;
43
+ methods?: string[];
44
+ allowedHeaders?: string[];
45
+ };
46
+ }
47
+ export interface LaunchPlaygroundResult {
48
+ /**
49
+ * The playground server instance
50
+ */
51
+ server: PlaygroundServer;
52
+ /**
53
+ * The server port
54
+ */
55
+ port: number;
56
+ /**
57
+ * The server host
58
+ */
59
+ host: string;
60
+ /**
61
+ * Function to gracefully shutdown the playground
62
+ */
63
+ close: () => Promise<void>;
64
+ }
65
+ /**
66
+ * Create a playground launcher for a specific agent
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * import { playgroundForAgent } from '@sqaitech/playground';
71
+ * import { SampleDevice, Agent } from '@sqaitech/core';
72
+ *
73
+ * const device = new SampleDevice();
74
+ * const agent = new Agent(device);
75
+ *
76
+ * // Launch playground for the agent
77
+ * const server = await playgroundForAgent(agent).launch();
78
+ *
79
+ * // Launch with CORS enabled
80
+ * const serverWithCors = await playgroundForAgent(agent).launch({
81
+ * enableCors: true,
82
+ * corsOptions: {
83
+ * origin: ['http://localhost:3000', 'http://localhost:8080'],
84
+ * credentials: true
85
+ * }
86
+ * });
87
+ *
88
+ * // Later, when you want to shutdown:
89
+ * server.close();
90
+ * ```
91
+ */
92
+ export declare function playgroundForAgent(agent: Agent): {
93
+ /**
94
+ * Launch the playground server with optional configuration
95
+ */
96
+ launch(options?: LaunchPlaygroundOptions): Promise<LaunchPlaygroundResult>;
97
+ };
@@ -0,0 +1,31 @@
1
+ import type { DeviceAction } from '@sqaitech/core';
2
+ import type { ExecutionOptions, FormValue, PlaygroundConfig, ValidationResult } from '../types';
3
+ export declare class PlaygroundSDK {
4
+ private adapter;
5
+ constructor(config: PlaygroundConfig);
6
+ private createAdapter;
7
+ executeAction(actionType: string, value: FormValue, options: ExecutionOptions): Promise<unknown>;
8
+ getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]>;
9
+ validateStructuredParams(value: FormValue, action: DeviceAction<unknown> | undefined): ValidationResult;
10
+ formatErrorMessage(error: any): string;
11
+ createDisplayContent(value: FormValue, needsStructuredParams: boolean, action: DeviceAction<unknown> | undefined): string;
12
+ get id(): string | undefined;
13
+ checkStatus(): Promise<boolean>;
14
+ overrideConfig(aiConfig: any): Promise<void>;
15
+ getTaskProgress(requestId: string): Promise<{
16
+ tip?: string;
17
+ }>;
18
+ cancelTask(requestId: string): Promise<any>;
19
+ onProgressUpdate(callback: (tip: string) => void): void;
20
+ startProgressPolling(requestId: string): void;
21
+ stopProgressPolling(requestId: string): void;
22
+ cancelExecution(requestId: string): Promise<void>;
23
+ getScreenshot(): Promise<{
24
+ screenshot: string;
25
+ timestamp: number;
26
+ } | null>;
27
+ getInterfaceInfo(): Promise<{
28
+ type: string;
29
+ description?: string;
30
+ } | null>;
31
+ }
@@ -0,0 +1,75 @@
1
+ import type { Server } from 'node:http';
2
+ import type { Agent as PageAgent } from '@sqaitech/core/agent';
3
+ import express from 'express';
4
+ import 'dotenv/config';
5
+ declare class PlaygroundServer {
6
+ private _app;
7
+ tmpDir: string;
8
+ server?: Server;
9
+ port?: number | null;
10
+ agent: PageAgent;
11
+ staticPath: string;
12
+ taskProgressTips: Record<string, string>;
13
+ id: string;
14
+ private _initialized;
15
+ private agentFactory?;
16
+ private currentTaskId;
17
+ constructor(agent: PageAgent | (() => PageAgent) | (() => Promise<PageAgent>), staticPath?: string, id?: string);
18
+ /**
19
+ * Get the Express app instance for custom configuration
20
+ *
21
+ * IMPORTANT: Add middleware (like CORS) BEFORE calling launch()
22
+ * The routes are initialized when launch() is called, so middleware
23
+ * added after launch() will not affect the API routes.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * import cors from 'cors';
28
+ *
29
+ * const server = new PlaygroundServer(agent);
30
+ *
31
+ * // Add CORS middleware before launch
32
+ * server.app.use(cors({
33
+ * origin: true,
34
+ * credentials: true,
35
+ * methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']
36
+ * }));
37
+ *
38
+ * await server.launch();
39
+ * ```
40
+ */
41
+ get app(): express.Application;
42
+ /**
43
+ * Initialize Express app with all routes and middleware
44
+ * Called automatically by launch() if not already initialized
45
+ */
46
+ private initializeApp;
47
+ filePathForUuid(uuid: string): string;
48
+ saveContextFile(uuid: string, context: string): string;
49
+ /**
50
+ * Recreate agent instance (for cancellation)
51
+ */
52
+ private recreateAgent;
53
+ /**
54
+ * Setup all API routes
55
+ */
56
+ private setupRoutes;
57
+ /**
58
+ * Setup static file serving routes
59
+ */
60
+ private setupStaticRoutes;
61
+ /**
62
+ * Serve HTML with injected port configuration
63
+ */
64
+ private serveHtmlWithPorts;
65
+ /**
66
+ * Launch the server on specified port
67
+ */
68
+ launch(port?: number): Promise<PlaygroundServer>;
69
+ /**
70
+ * Close the server and clean up resources
71
+ */
72
+ close(): Promise<void>;
73
+ }
74
+ export default PlaygroundServer;
75
+ export { PlaygroundServer };
@@ -0,0 +1,49 @@
1
+ import type { DeviceAction, WebUIContext } from '@sqaitech/core';
2
+ import type { Agent } from '@sqaitech/core/agent';
3
+ export interface PlaygroundAgent extends Agent {
4
+ [key: string]: any;
5
+ }
6
+ export interface FormValue {
7
+ type: string;
8
+ prompt?: string;
9
+ params?: Record<string, unknown>;
10
+ }
11
+ export interface ValidationResult {
12
+ valid: boolean;
13
+ errorMessage?: string;
14
+ }
15
+ export interface ServerResponse {
16
+ result?: unknown;
17
+ dump?: any;
18
+ reportHTML?: string;
19
+ error?: string;
20
+ }
21
+ export interface ExecutionOptions {
22
+ deepThink?: boolean;
23
+ screenshotIncluded?: boolean;
24
+ domIncluded?: boolean | 'visible-only';
25
+ context?: any;
26
+ requestId?: string;
27
+ }
28
+ export type PlaygroundWebUIContext = WebUIContext & {
29
+ screenshotBase64?: string;
30
+ size: {
31
+ width: number;
32
+ height: number;
33
+ dpr?: number;
34
+ };
35
+ };
36
+ export type ExecutionType = 'local-execution' | 'remote-execution';
37
+ export interface PlaygroundConfig {
38
+ type: ExecutionType;
39
+ serverUrl?: string;
40
+ agent?: PlaygroundAgent;
41
+ }
42
+ export interface PlaygroundAdapter {
43
+ parseStructuredParams(action: DeviceAction<unknown>, params: Record<string, unknown>, options: ExecutionOptions): Promise<unknown[]>;
44
+ formatErrorMessage(error: any): string;
45
+ validateParams(value: FormValue, action: DeviceAction<unknown> | undefined): ValidationResult;
46
+ createDisplayContent(value: FormValue, needsStructuredParams: boolean, action: DeviceAction<unknown> | undefined): string;
47
+ executeAction(activeAgent: PlaygroundAgent, actionType: string, actionSpace: DeviceAction<unknown>[], value: FormValue, options: ExecutionOptions): Promise<unknown>;
48
+ getActionSpace?(context: any): Promise<DeviceAction<unknown>[]>;
49
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@sqaitech/playground",
3
+ "version": "0.30.10",
4
+ "description": "SQAI playground utilities for web integration",
5
+ "author": "sqai team",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/types/index.d.ts",
10
+ "browser": {
11
+ "require": "./dist/lib/index.browser.js",
12
+ "import": "./dist/es/index.browser.mjs"
13
+ },
14
+ "require": "./dist/lib/index.js",
15
+ "import": "./dist/es/index.mjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "static"
21
+ ],
22
+ "dependencies": {
23
+ "cors": "^2.8.5",
24
+ "dotenv": "^16.4.5",
25
+ "express": "^4.21.2",
26
+ "open": "10.1.0",
27
+ "uuid": "11.1.0",
28
+ "@sqaitech/core": "0.30.10",
29
+ "@sqaitech/shared": "0.30.10"
30
+ },
31
+ "devDependencies": {
32
+ "@rslib/core": "^0.11.2",
33
+ "@types/cors": "^2.8.17",
34
+ "@types/express": "^4.17.21",
35
+ "@types/node": "^18.0.0",
36
+ "@types/uuid": "10.0.0",
37
+ "typescript": "^5.8.3",
38
+ "vitest": "3.0.5"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "scripts": {
44
+ "build": "rslib build",
45
+ "build:watch": "rslib build --watch",
46
+ "dev": "rslib build --watch",
47
+ "test": "vitest --run",
48
+ "test:watch": "vitest",
49
+ "type-check": "tsc --noEmit"
50
+ }
51
+ }
Binary file
@@ -0,0 +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.f566a9ed.js"></script><script defer src="/static/js/931.dc961e99.js"></script><script defer src="/static/js/index.5cccbdaf.js"></script><link href="/static/css/index.60c69390.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
@@ -0,0 +1,2 @@
1
+ body{margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;font-size:14px}h3{text-transform:capitalize}.app-container{background-color:#f5f5f5;flex-direction:column;width:100%;height:100vh;display:flex}.app-content{height:100vh;overflow:hidden}.app-grid-layout{height:100%;display:flex}.app-grid-layout .ant-row{flex-wrap:nowrap;flex:1;width:100%;height:100%;display:flex}.app-panel{background-color:#fff;border-radius:0;height:100%;transition:box-shadow .3s;overflow:hidden;box-shadow:0 1px 2px #0000000d}.app-panel:hover{box-shadow:0 2px 8px #00000017}.app-panel.left-panel{flex-direction:column;height:100%;display:flex;overflow:hidden}.app-panel.right-panel{border-radius:0;flex:1;overflow:hidden;box-shadow:-4px 0 20px #0000000a}.panel-content{flex-direction:column;height:100%;display:flex;overflow:auto}.panel-content.left-panel-content{flex-direction:column;height:100%;display:flex;overflow:hidden}.panel-content.left-panel-content .playground-panel-header{border-bottom:1px solid #0000000f;flex-shrink:0;align-items:center;height:60px;padding:0 24px;display:flex}.panel-content.left-panel-content .playground-panel-header .header-row{justify-content:space-between;align-items:center;gap:10px;width:100%;display:flex}.panel-content.left-panel-content .playground-panel-header h2{color:#1890ff;margin:0 0 16px;font-size:18px;font-weight:600}.panel-content.left-panel-content .playground-panel-playground{flex-direction:column;flex:1;min-height:0;padding:0 24px;display:flex}.panel-content.left-panel-content .playground-panel-playground .playground-container{background:#fff;border:none;border-radius:8px;flex:1;overflow:hidden}.panel-content.right-panel-content{border-radius:0;padding:0 24px 24px}.server-offline-container{background:#f5f5f5;justify-content:center;align-items:center;height:100vh;display:flex}.server-offline-container .server-offline-message{background:#f2f4f7;border-radius:8px;flex-direction:column;width:100%;height:100%;padding:14px 24px 0;display:flex;box-shadow:0 2px 8px #0000000f}.server-offline-container .server-offline-message .server-offline-content{text-align:center;flex-direction:column;flex:1;justify-content:flex-start;align-items:center;padding-top:20vh;display:flex}.server-offline-container .server-offline-message .server-offline-icon{display:inline-block;position:relative}.server-offline-container .server-offline-message .server-offline-icon .icon-background,.server-offline-container .server-offline-message .server-offline-icon .icon-foreground{display:block;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.server-offline-container .server-offline-message .server-offline-icon .icon-background{z-index:1;width:300px;height:212px}.server-offline-container .server-offline-message .server-offline-icon .icon-foreground{z-index:2;width:134px;height:101px}.server-offline-container .server-offline-message .server-offline-icon:after{content:"";width:300px;height:212px;display:block;position:relative}.server-offline-container .server-offline-message h1{letter-spacing:0%;color:#000;margin:0;font-size:18px;font-weight:600}.server-offline-container .server-offline-message .connection-status{letter-spacing:0%;text-align:center;margin-top:8px;font-size:12px}.screenshot-viewer{flex-direction:column;height:100%;display:flex}.screenshot-viewer.offline,.screenshot-viewer.loading,.screenshot-viewer.error{text-align:center;color:#666;justify-content:center;align-items:center}.screenshot-viewer.offline .screenshot-placeholder h3,.screenshot-viewer.loading .screenshot-placeholder h3,.screenshot-viewer.error .screenshot-placeholder h3{color:#1890ff;text-transform:capitalize;margin-bottom:12px;font-size:18px}.screenshot-viewer.offline .screenshot-placeholder p,.screenshot-viewer.loading .screenshot-placeholder p,.screenshot-viewer.error .screenshot-placeholder p{color:#666;margin:0}.screenshot-viewer.offline .screenshot-placeholder p.error-message,.screenshot-viewer.loading .screenshot-placeholder p.error-message,.screenshot-viewer.error .screenshot-placeholder p.error-message{color:#ff4d4f}.screenshot-viewer .screenshot-header{justify-content:space-between;align-items:center;height:56px;display:flex}.screenshot-viewer .screenshot-header .screenshot-title{flex-direction:column;gap:4px;display:flex}.screenshot-viewer .screenshot-header .screenshot-title h3{color:#000;text-transform:capitalize;align-items:center;gap:8px;margin:0;font-size:14px;font-weight:600;display:flex}.screenshot-viewer .screenshot-header .screenshot-title h3:before{content:"";background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEyIiBmaWxsPSIjMEQ3MkZGIi8+DQo8cGF0aCBkPSJNMTQuNSA2Ljk5OTk4SDkuNUM5LjA4NTc5IDYuOTk5OTggOC43NSA3LjMzNTc3IDguNzUgNy43NDk5OFYxNi4yNUM4Ljc1IDE2LjY2NDIgOS4wODU3OSAxNyA5LjUgMTdIMTQuNUMxNC45MTQyIDE3IDE1LjI1IDE2LjY2NDIgMTUuMjUgMTYuMjVWNy43NDk5OEMxNS4yNSA3LjMzNTc3IDE0LjkxNDIgNi45OTk5OCAxNC41IDYuOTk5OThaIiBzdHJva2U9IndoaXRlIi8+DQo8cGF0aCBkPSJNMTEuNSA4LjQ5OTk4SDEyLjUiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPg0KPHBhdGggZD0iTTExIDE1LjVIMTMiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPg0KPC9zdmc+DQo=);background-position:50%;background-repeat:no-repeat;background-size:contain;width:24px;height:24px}.screenshot-viewer .screenshot-header .screenshot-title .screenshot-subtitle{color:#999;margin:0;font-size:12px}.screenshot-viewer .screenshot-container{background:#f2f4f7;border-radius:16px;flex-direction:column;flex:1;padding:0 15px;display:flex;overflow:hidden}.screenshot-viewer .screenshot-container .screenshot-overlay{z-index:10;justify-content:space-between;align-items:flex-start;padding:12px 5px 8px;display:flex}.screenshot-viewer .screenshot-container .screenshot-overlay .device-name-overlay{color:#000000d9;text-transform:capitalize;align-items:center;gap:8px;font-size:12px;font-weight:500;display:flex}.screenshot-viewer .screenshot-container .screenshot-overlay .device-name-overlay .info-icon{opacity:.8;cursor:pointer;font-size:12px}.screenshot-viewer .screenshot-container .screenshot-overlay .device-name-overlay .info-icon:hover{opacity:1}.screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls{opacity:1;box-sizing:border-box;border-radius:4px;align-items:center;gap:10px;height:18px;padding:4px 8px;display:flex}.screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .last-update-time{color:#666;white-space:nowrap;text-overflow:ellipsis;font-size:12px;overflow:hidden}.screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .operation-indicator{align-items:center;gap:4px;font-size:12px;display:flex}.screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .ant-btn{box-shadow:none;background:0 0;border:none;justify-content:center;align-items:center;width:16px;min-width:16px;height:16px;padding:0;display:flex}.screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .ant-btn:hover{background-color:#0000000f;border-radius:2px;transition:all .2s;transform:scale(1.1)}.screenshot-viewer .screenshot-container .screenshot-overlay .screenshot-controls .ant-btn .anticon{color:#666;font-size:12px;transition:color .2s}.screenshot-viewer .screenshot-container .screenshot-content{flex:1;justify-content:center;align-items:center;min-height:0;display:flex}.screenshot-viewer .screenshot-container .screenshot-content .screenshot-image{object-fit:contain;border-radius:12px;max-width:100%;height:auto;max-height:100%}.screenshot-viewer .screenshot-container .screenshot-content .screenshot-placeholder{text-align:center;color:#999}.panel-resize-handle{background-color:#f0f0f0;transition:background-color .2s;position:relative}.panel-resize-handle.horizontal{cursor:col-resize;width:1px}.panel-resize-handle.vertical{cursor:row-resize;height:1px}.panel-resize-handle:hover,.panel-resize-handle:active,.panel-resize-handle[data-resize-handle-active]{background-color:#1677ff}.clear-button-container{top:20px!important;right:-4px!important}.logo img{vertical-align:baseline;height:30px;vertical-align:-webkit-baseline-middle;line-height:30px}.logo-with-star-wrapper{flex-direction:row;justify-content:space-between;display:flex}.nav-actions{align-items:center;gap:8px;display:flex}.nav-actions .nav-icon{color:#000000a6;cursor:pointer;font-size:16px;transition:color .3s}.nav-actions .nav-icon:hover{color:#2b83ff}.nav-actions a{align-items:center;text-decoration:none;display:flex}.nav-actions a:hover .nav-icon{color:#2b83ff}[data-theme=dark] .nav-actions .nav-icon{color:#ffffffa6}[data-theme=dark] .nav-actions .nav-icon:hover{color:#2b83ff}.blackboard .footer{color:#aaa}.blackboard ul{padding-left:0}.blackboard li{list-style:none}.blackboard .bottom-tip{height:30px}.blackboard .bottom-tip-item{color:#aaa;text-overflow:ellipsis;word-wrap:break-word;max-width:500px}.blackboard-filter{margin:10px 0}.blackboard-main-content canvas{box-sizing:border-box;border:1px solid #888;width:100%}.shiny-text{color:#0000;letter-spacing:.5px;text-shadow:0 1px 2px #0000000d;background-image:linear-gradient(45deg,#2b83ff,#6a11cb,#2575fc,#4481eb);background-size:300%;-webkit-background-clip:text;background-clip:text;font-weight:600;animation:8s infinite textGradient;display:inline-block;position:relative;overflow:hidden}.shiny-text:after{content:"";width:120%;height:120%;animation:shine var(--animation-duration,5s)cubic-bezier(.25,.1,.25,1)infinite;z-index:1;pointer-events:none;background:linear-gradient(90deg,#fff0 0%,#ffffff1a 10%,#fff9 50%,#ffffff1a 90%,#fff0 100%);position:absolute;top:-10%;left:-150%;transform:skew(-20deg)translateY(0)}.shiny-text.disabled{background:#2b83ff;-webkit-background-clip:text;background-clip:text;animation:none}.shiny-text.disabled:after{animation:none;display:none}@keyframes shine{0%{opacity:.7;left:-150%}20%{opacity:1}80%{opacity:1}to{opacity:.7;left:250%}}@keyframes textGradient{0%{background-position:0%}50%{background-position:100%}to{background-position:0%}}.env-config-reminder{background:#fff2e8;border-radius:12px;align-items:center;gap:12px;margin-bottom:12px;padding:12px 16px;display:flex}.env-config-reminder .reminder-icon{color:#fa541c;width:16px;height:16px}.env-config-reminder .reminder-text{color:#000;flex:1;font-size:14px}.player-container{box-sizing:border-box;background:#f2f4f7;border:1px solid #f2f4f7;border-radius:8px;flex-direction:column;width:100%;max-width:100%;height:100%;min-height:300px;max-height:100%;margin:0 auto;padding:12px;line-height:100%;display:flex;position:relative;overflow:visible}.player-container[data-fit-mode=height]{background:#fff}.player-container[data-fit-mode=height] .canvas-container{background-color:#f2f4f7}.player-container .canvas-container{width:100%;min-height:200px;aspect-ratio:var(--canvas-aspect-ratio,16/9);background-color:#fff;border-top-left-radius:4px;border-top-right-radius:4px;flex:none;justify-content:center;align-items:center;display:flex;position:relative;overflow:hidden}.player-container .canvas-container canvas{box-sizing:border-box;object-fit:contain;border:none;width:100%;max-width:100%;height:auto;max-height:100%;margin:0 auto;display:block}.player-container .canvas-container[data-fit-mode=height]{aspect-ratio:unset;flex:auto;height:auto;min-height:0}.player-container .canvas-container[data-fit-mode=height] canvas{width:auto;max-width:100%;height:100%;max-height:100%}.player-container .canvas-container[data-fit-mode=width]{aspect-ratio:var(--canvas-aspect-ratio,16/9)}.player-container .canvas-container[data-fit-mode=width] canvas{width:100%;height:auto}.player-container .player-timeline-wrapper{flex:none;width:100%;height:4px;margin-bottom:2px;position:relative}.player-container .player-timeline{background:#666;flex-shrink:0;width:100%;height:4px;position:relative}.player-container .player-timeline .player-timeline-progress{background:#2b83ff;height:4px;transition-timing-function:linear;position:absolute;top:0;left:0}.player-container .player-tools-wrapper{box-sizing:border-box;flex:none;width:100%;height:72px;padding:15px 16px;position:relative}.player-container .player-tools{color:#000;box-sizing:border-box;flex-direction:row;flex-shrink:0;justify-content:space-between;width:100%;max-width:100%;height:42px;font-size:14px;display:flex;overflow:hidden}.player-container .player-tools .ant-spin{color:#333}.player-container .player-tools .player-control{flex-direction:row;flex-grow:1;align-items:center;display:flex;overflow:hidden}.player-container .player-tools .status-icon{border-radius:8px;flex-shrink:0;justify-content:center;align-items:center;width:32px;height:32px;margin-left:10px;transition:all .2s;display:flex}.player-container .player-tools .status-icon:hover{cursor:pointer;background:#f0f0f0}.player-container .player-tools .status-text{flex-direction:column;flex-grow:1;flex-shrink:1;justify-content:space-between;width:0;min-width:0;height:100%;display:flex;position:relative;overflow:hidden}.player-container .player-tools .title{font-weight:600}.player-container .player-tools .title,.player-container .player-tools .subtitle{text-overflow:ellipsis;white-space:nowrap;width:100%;overflow:hidden}.player-container .player-tools .player-tools-item{flex-direction:column;justify-content:center;height:100%;display:flex}.result-wrapper{justify-content:center;height:100%;margin:4px 0;display:flex}.result-wrapper .loading-container{flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%;display:flex}.result-wrapper .loading-container .loading-progress-text{color:#888;margin-top:8px;font-size:12px}.result-wrapper pre{white-space:pre-wrap;text-wrap:unset;word-wrap:break-word;overflow-wrap:break-word;background:#f2f4f7;border-radius:8px;margin:0;padding:14px;overflow:scroll}.playground-container{background:#fff;flex-direction:column;width:100%;height:100vh;display:flex;position:relative}.playground-container .command-form{flex-direction:column;width:100%;height:100%;display:flex}.playground-container .context-preview-section{border-bottom:1px solid #f0f0f0;flex-shrink:0;padding:16px}.playground-container .middle-dialog-area{flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.playground-container .middle-dialog-area .clear-button-container{z-index:10;position:absolute;top:16px;right:0}.playground-container .middle-dialog-area .clear-button-container .clear-button{opacity:.7;transition:opacity .2s}.playground-container .middle-dialog-area .clear-button-container .clear-button:hover{opacity:1}.playground-container .middle-dialog-area .info-list-container{scrollbar-width:none;flex:1;padding-top:16px;padding-bottom:16px;overflow:hidden auto}.playground-container .middle-dialog-area .info-list-container .ant-list .ant-list-item{border-bottom:none;padding:0}.playground-container .middle-dialog-area .info-list-container .ant-list .ant-list-item .ant-card{border:1px solid #f0f0f0;border-radius:8px;box-shadow:0 1px 3px #0000001a}.playground-container .middle-dialog-area .info-list-container .ant-list .ant-list-item .ant-card:hover{box-shadow:0 2px 6px #00000026}.playground-container .middle-dialog-area .info-list-container .ant-list .ant-list-item .ant-card .ant-card-body{padding:12px}.playground-container .middle-dialog-area .info-list-container .ant-list .ant-list-empty-text{color:#999;font-style:italic}.playground-container .middle-dialog-area .info-list-container::-webkit-scrollbar{display:none}.playground-container .middle-dialog-area .info-list-container .list-item{background:0 0;border:none;padding:0}.playground-container .middle-dialog-area .scroll-to-bottom-button{z-index:10;background:#fff;border:1px solid #00000014;position:absolute;bottom:10px;right:0}.playground-container .middle-dialog-area .scroll-to-bottom-button:hover{background:#1890ff}.playground-container .middle-dialog-area .scroll-to-bottom-button:hover .anticon{color:#fff}.playground-container .middle-dialog-area .scroll-to-bottom-button .anticon{color:#333;font-size:16px}.playground-container .user-message-container{justify-content:flex-end;width:100%;margin:20px 0 30px;display:flex}.playground-container .user-message-container .user-message-bubble{color:#000000d9;text-align:left;background:#f2f4f7;border-radius:12px;max-width:80%;padding:12px 16px;font-size:14px;font-weight:400;display:inline-block}.playground-container .progress-action-item{color:#000;background:#f2f4f7;border-radius:8px;justify-content:space-between;height:36px;margin:4px 0;padding:0 12px;font-size:14px;line-height:36px;display:flex}.playground-container .progress-action-item .progress-status-icon{margin-left:4px}.playground-container .progress-action-item .progress-status-icon.loading{color:#1890ff}.playground-container .progress-action-item .progress-status-icon.completed{color:#52c41a}.playground-container .progress-action-item .progress-status-icon.error{color:#ff4d4f;font-weight:700}.playground-container .progress-description{color:#000;padding:8px 0;font-size:14px;line-height:22px;display:inline-block}.playground-container .system-message-container{flex-direction:column;display:flex}.playground-container .system-message-container .system-message-header{align-items:center;gap:8px;margin:12px 0;display:flex}.playground-container .system-message-container .system-message-header .system-message-title{font-size:12px;font-weight:400;line-height:100%}.playground-container .system-message-container .system-message-content{color:#000000d9;font-size:14px}.playground-container .system-message-container .system-message-content .system-message-text{color:#000000d9;font-size:14px;line-height:25px}.playground-container .system-message-container .system-message-content .error-message{color:#e51723;word-break:break-word;background-color:#fff;border:none;border-radius:0;align-items:flex-start;margin-bottom:16px;padding:0;font-size:14px;display:flex}.playground-container .system-message-container .system-message-content .error-message .divider{background-color:#e6e8eb;flex-shrink:0;align-self:stretch;width:1px;min-height:20px;margin:0 8px 0 0}.playground-container .system-message-container .system-message-content .loading-progress-text{color:#666;background:#f6f8fa;border-left:3px solid #1890ff;border-radius:4px;margin-top:8px;padding:8px 12px;font-size:13px}.playground-container .new-conversation-separator{flex-shrink:0;justify-content:center;align-items:center;padding:20px 0;display:flex;position:relative}.playground-container .new-conversation-separator .separator-line{background-color:#e8e8e8;height:1px;position:absolute;top:50%;left:0;right:0}.playground-container .new-conversation-separator .separator-text-container{z-index:1;background-color:#fff;padding:0 16px;position:relative}.playground-container .new-conversation-separator .separator-text-container .separator-text{color:#999;background-color:#fff;font-size:12px}.playground-container .bottom-input-section{background-color:#fff;flex-shrink:0;padding:16px 0 0}.playground-container .version-info-section{flex-shrink:0;justify-content:center;align-items:center;height:38px;display:flex}.playground-container .version-text{color:#999;text-align:center;font-size:12px}.playground-container .hidden-result-ref{display:none}.playground-container .playground-description{margin-bottom:32px}.playground-container .playground-description .description-zh{color:#333;margin:0 0 8px;font-size:16px;line-height:1.5}.playground-container .playground-description .description-en{color:#666;margin:0;font-size:14px;line-height:1.5}.playground-container .config-section{margin-bottom:24px}.playground-container .config-section .config-title{color:#333;margin:0 0 16px;font-size:18px;font-weight:600}.playground-container .config-section .config-item{align-items:center;gap:8px;margin-bottom:12px;display:flex}.playground-container .config-section .config-item .config-check{color:#52c41a;font-size:16px}.playground-container .config-section .config-item .config-label{color:#333;font-size:14px}.playground-container .config-section .config-link{color:#1890ff;font-size:14px;text-decoration:none}.playground-container .config-section .config-link:hover{text-decoration:underline}.prompt-input-wrapper{width:100%}.prompt-input-wrapper .mode-radio-group-wrapper{align-items:center;gap:8px;display:flex;position:relative}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group{scrollbar-width:thin;flex:1;align-items:center;gap:8px;min-width:0;height:100%;margin-right:60px;display:flex;overflow:auto hidden}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar{height:6px}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-thumb:hover{background:#a8a8a8}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-form-item{flex-shrink:0;margin:0!important}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-form-item .ant-radio-group{flex-wrap:nowrap;gap:8px;display:flex}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-radio-button-wrapper{height:24px;box-shadow:none;white-space:nowrap;background-color:#f7f7f7;border:none;border-radius:11px;flex-shrink:0;margin-right:0;padding:0 8px;font-size:12px;line-height:24px}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-radio-button-wrapper:before{display:none}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-radio-button-wrapper:focus-within{outline:none}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-radio-button-wrapper.ant-radio-button-wrapper-checked{color:#fff;background-color:#2b83ff;border-color:#2b83ff}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-radio-button-wrapper.ant-radio-button-wrapper-checked:hover{color:#fff}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-dropdown-trigger{flex-shrink:0}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button{height:24px;box-shadow:none;white-space:nowrap;background-color:#f7f7f7;border:none;border-radius:11px;flex-shrink:0;align-items:center;gap:2px;max-width:160px;padding:0 8px;font-size:12px;display:inline-flex}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button .ant-btn-content{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button:hover{background-color:#e6e6e6}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button.selected-from-dropdown{color:#fff;background-color:#2b83ff;font-weight:500}.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button.selected-from-dropdown:hover{background-color:#2b83ff}.prompt-input-wrapper .mode-radio-group-wrapper .action-icons{z-index:10;pointer-events:none;background:linear-gradient(90deg,#0000 0%,#ffffff80 20%,#fffc 40%,#fffffff2 60%,#fff 70%);flex-shrink:0;justify-content:flex-end;align-items:center;gap:8px;width:80px;padding-left:20px;display:flex;position:absolute;top:50%;right:0;transform:translateY(-50%)}.prompt-input-wrapper .mode-radio-group-wrapper .action-icons>*{pointer-events:auto}.prompt-input-wrapper .main-side-console-input{margin-top:10px;position:relative}.prompt-input-wrapper .main-side-console-input .main-side-console-input-textarea{white-space:pre-wrap;scrollbar-width:thin;background:#fff;border:1px solid #f2f4f7;border-radius:12px;padding:12px 16px;line-height:21px;transition:background-color .2s;overflow-y:auto}@keyframes hue-shift{0%{filter:hue-rotate()}to{filter:hue-rotate(360deg)}}.prompt-input-wrapper .main-side-console-input .main-side-console-input-textarea:focus-within{background:linear-gradient(#fff,#fff) padding-box padding-box,linear-gradient(135deg,#4285f4 0%,#06f 25%,#7b02c5 50%,#ea4335 75%,#ff7043 100%) border-box;border:1px solid #0000}.prompt-input-wrapper .main-side-console-input .main-side-console-input-textarea::-webkit-scrollbar{width:6px}.prompt-input-wrapper .main-side-console-input .main-side-console-input-textarea::-webkit-scrollbar-thumb{background-color:#0003;border-radius:3px}.prompt-input-wrapper .main-side-console-input.loading .main-side-console-input-textarea{background:linear-gradient(#fff,#fff) padding-box padding-box,linear-gradient(135deg,#4285f4 0%,#06f 25%,#7b02c5 50%,#ea4335 75%,#ff7043 100%) border-box;border:1px solid #0000;animation:5s linear infinite hue-shift}.prompt-input-wrapper .main-side-console-input .ant-form-item-control-input-content{z-index:999;border:3px solid #0000;border-radius:14px}.prompt-input-wrapper .main-side-console-input:focus-within .ant-form-item-control-input-content{border-color:#2b83ff29}.prompt-input-wrapper .main-side-console-input.disabled .form-controller-wrapper{background-color:#0000}.prompt-input-wrapper .ant-form-item-with-help+.form-controller-wrapper{bottom:22px}.prompt-input-wrapper .ant-input{padding-bottom:40px}.prompt-input-wrapper .form-controller-wrapper{box-sizing:border-box;background-color:#fff;flex-direction:row;justify-content:flex-end;align-items:flex-end;gap:8px;width:calc(100% - 32px);padding:12px 0;line-height:32px;transition:background-color .2s;display:flex;position:absolute;bottom:1px;left:16px}.prompt-input-wrapper .settings-wrapper{color:#777;flex-flow:wrap;gap:2px;display:flex}.prompt-input-wrapper .settings-wrapper.settings-wrapper-hover{color:#3b3b3b}.prompt-input-wrapper .structured-params-container{background:linear-gradient(#fff,#fff) padding-box padding-box,linear-gradient(135deg,#4285f4 0%,#06f 25%,#7b02c5 50%,#ea4335 75%,#ff7043 100%) border-box;border:1px solid #0000;border-radius:12px;padding:16px 16px 56px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item{flex-direction:column;display:flex}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label{text-align:left;flex-basis:auto;padding-bottom:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label{color:#000000d9;height:auto;font-size:12px;font-weight:500;line-height:1.5}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:after{color:#ff4d4f;font-family:SimSun,sans-serif;font-size:12px;line-height:1;display:inline-block}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:not(:-webkit-any(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))):after{margin-left:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:not(:-moz-any(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))):after{margin-left:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:not(:-webkit-any(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))):after{margin-left:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:not(:-moz-any(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))):after{margin-left:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:not(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi))):after{margin-left:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:-webkit-any(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)):after{margin-right:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:-moz-any(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)):after{margin-right:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-label>label:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)):after{margin-right:4px}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-control{flex:1;margin-top:0}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-row{flex-direction:column}.prompt-input-wrapper .structured-params-container .structured-params .ant-form-item .ant-form-item-control-input{min-height:auto}.prompt-input-wrapper .structured-params-container .structured-params .ant-input,.prompt-input-wrapper .structured-params-container .structured-params .ant-input-number,.prompt-input-wrapper .structured-params-container .structured-params .ant-select{border:1px solid #e1e5e9;border-radius:6px;width:100%}.prompt-input-wrapper .structured-params-container .structured-params .ant-input:hover,.prompt-input-wrapper .structured-params-container .structured-params .ant-input-number:hover,.prompt-input-wrapper .structured-params-container .structured-params .ant-select:hover{border-color:#40a9ff}.prompt-input-wrapper .structured-params-container .structured-params .ant-input:focus,.prompt-input-wrapper .structured-params-container .structured-params .ant-input-number:focus,.prompt-input-wrapper .structured-params-container .structured-params .ant-select:focus,.prompt-input-wrapper .structured-params-container .structured-params .ant-input:focus-within,.prompt-input-wrapper .structured-params-container .structured-params .ant-input-number:focus-within,.prompt-input-wrapper .structured-params-container .structured-params .ant-select:focus-within{border-color:#40a9ff;box-shadow:0 0 0 2px #1890ff33}.prompt-input-wrapper .structured-params-container .structured-params textarea.ant-input{padding-bottom:5px}.prompt-input-wrapper .structured-params-container .structured-params .ant-input-number .ant-input-number-input{box-shadow:none;border:none}.prompt-input-wrapper .structured-params-container .structured-params .ant-input-number:hover .ant-input-number-input{box-shadow:none}.prompt-input-wrapper .structured-params-container .structured-params .ant-select{min-width:120px}.prompt-input-wrapper .structured-params-container .structured-params .ant-select .ant-select-selector{box-shadow:none;border:none}.prompt-input-wrapper .structured-params-container .structured-params .ant-select:hover .ant-select-selector,.prompt-input-wrapper .structured-params-container .structured-params .ant-select.ant-select-focused .ant-select-selector{box-shadow:none}.prompt-input-wrapper .structured-params-container .structured-params .ant-radio-group{width:100%}.prompt-input-wrapper .structured-params-container .structured-params .ant-radio-group .ant-radio-button-wrapper{border:1px solid #e1e5e9;border-radius:6px;height:32px;margin-right:4px;font-size:12px;line-height:30px}.prompt-input-wrapper .structured-params-container .structured-params .ant-radio-group .ant-radio-button-wrapper.ant-radio-button-wrapper-checked{color:#fff;background-color:#2b83ff;border-color:#2b83ff}.selector-trigger{cursor:pointer;width:24px;height:24px;transition:all .2s}.selector-trigger .action-icon{color:#000000d9;font-size:14px;transition:all .2s}.selector-trigger .action-icon:hover{color:#2b83ff}.history-selector-wrapper{position:relative}.history-modal-overlay{z-index:9999;background:#fff;border:1px solid #00000014;border-radius:12px;width:320px;height:400px;position:fixed;top:auto;bottom:20px;right:20px;box-shadow:0 8px 24px #0000001f}.history-modal-container{border-radius:12px;flex-direction:column;width:100%;height:100%;display:flex;overflow:hidden}.history-modal-container .history-modal-header{justify-content:space-between;align-items:center;height:48px;padding:0 25px;line-height:48px;display:flex}.history-modal-container .history-modal-header .close-button{justify-content:center;align-items:center;margin-right:-4px;padding:4px;display:flex}.history-modal-container .history-modal-header .close-button .anticon{color:#999;font-size:18px}.history-modal-container .history-modal-header .close-button:hover .anticon{color:#666}.history-modal-container .history-search-section{background:#fff;padding:16px 20px}.history-modal-container .history-search-section .search-input-wrapper{color:#00000040;align-items:center;gap:12px;display:flex}.history-modal-container .history-search-section .search-input-wrapper .search-input{background:#f1f2f3;border:none;border-radius:16px;flex:1;height:36px}.history-modal-container .history-search-section .search-input-wrapper .search-input .ant-input{box-shadow:none;background:0 0;border:none}.history-modal-container .history-search-section .search-input-wrapper .search-input:hover,.history-modal-container .history-search-section .search-input-wrapper .search-input:focus-within{background:#fff;border-color:#d9d9d9}.history-modal-container .history-search-section .search-input-wrapper .clear-button{color:#1890ff;height:auto;padding:0}.history-modal-container .history-search-section .search-input-wrapper .clear-button:hover{color:#40a9ff}.history-modal-container .history-content{flex:1;padding:0 25px 25px;overflow-y:auto}.history-modal-container .history-content .history-group{margin-bottom:10px}.history-modal-container .history-content .history-group .history-group-title{color:#00000073;height:40px;font-size:12px;font-weight:400;line-height:40px}.history-modal-container .history-content .history-group .history-item{cursor:pointer;color:#000000d9;white-space:nowrap;text-overflow:ellipsis;height:40px;font-size:14px;line-height:40px;overflow:hidden}.history-modal-container .history-content .history-group .history-item:hover{background:#f2f4f7;margin:0 -8px;padding:0 8px}.history-modal-container .history-content .no-results{text-align:center;color:#999;padding:40px 20px}
2
+ /*# sourceMappingURL=index.60c69390.css.map*/