@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.
- 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/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.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.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,385 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { getTmpDir } from "@sqaitech/core/utils";
|
|
5
|
+
import { PLAYGROUND_SERVER_PORT } from "@sqaitech/shared/constants";
|
|
6
|
+
import { overrideAIConfig } from "@sqaitech/shared/env";
|
|
7
|
+
import { uuid as utils_uuid } from "@sqaitech/shared/utils";
|
|
8
|
+
import express from "express";
|
|
9
|
+
import { executeAction, formatErrorMessage } from "./common.mjs";
|
|
10
|
+
import "dotenv/config";
|
|
11
|
+
function _define_property(obj, key, value) {
|
|
12
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
13
|
+
value: value,
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true
|
|
17
|
+
});
|
|
18
|
+
else obj[key] = value;
|
|
19
|
+
return obj;
|
|
20
|
+
}
|
|
21
|
+
const defaultPort = PLAYGROUND_SERVER_PORT;
|
|
22
|
+
const server_filename = fileURLToPath(import.meta.url);
|
|
23
|
+
const server_dirname = dirname(server_filename);
|
|
24
|
+
const STATIC_PATH = join(server_dirname, '..', '..', 'static');
|
|
25
|
+
const errorHandler = (err, req, res, next)=>{
|
|
26
|
+
console.error(err);
|
|
27
|
+
const errorMessage = err instanceof Error ? err.message : 'Internal server error';
|
|
28
|
+
res.status(500).json({
|
|
29
|
+
error: errorMessage
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
class PlaygroundServer {
|
|
33
|
+
get app() {
|
|
34
|
+
return this._app;
|
|
35
|
+
}
|
|
36
|
+
initializeApp() {
|
|
37
|
+
if (this._initialized) return;
|
|
38
|
+
this._app.use(express.json({
|
|
39
|
+
limit: '50mb'
|
|
40
|
+
}));
|
|
41
|
+
this._app.use((req, _res, next)=>{
|
|
42
|
+
const { context } = req.body || {};
|
|
43
|
+
if (context && 'updateContext' in this.agent.interface && 'function' == typeof this.agent.interface.updateContext) {
|
|
44
|
+
this.agent.interface.updateContext(context);
|
|
45
|
+
console.log('Context updated by PlaygroundServer middleware');
|
|
46
|
+
}
|
|
47
|
+
next();
|
|
48
|
+
});
|
|
49
|
+
this.setupRoutes();
|
|
50
|
+
this.setupStaticRoutes();
|
|
51
|
+
this._app.use(errorHandler);
|
|
52
|
+
this._initialized = true;
|
|
53
|
+
}
|
|
54
|
+
filePathForUuid(uuid) {
|
|
55
|
+
return join(this.tmpDir, `${uuid}.json`);
|
|
56
|
+
}
|
|
57
|
+
saveContextFile(uuid, context) {
|
|
58
|
+
const tmpFile = this.filePathForUuid(uuid);
|
|
59
|
+
console.log(`save context file: ${tmpFile}`);
|
|
60
|
+
writeFileSync(tmpFile, context);
|
|
61
|
+
return tmpFile;
|
|
62
|
+
}
|
|
63
|
+
async recreateAgent() {
|
|
64
|
+
if (!this.agentFactory) return void console.warn('Cannot recreate agent: factory function not provided. Agent recreation is only available when using factory mode.');
|
|
65
|
+
console.log('Recreating agent to cancel current task...');
|
|
66
|
+
try {
|
|
67
|
+
if (this.agent && 'function' == typeof this.agent.destroy) await this.agent.destroy();
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.warn('Failed to destroy old agent:', error);
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
this.agent = await this.agentFactory();
|
|
73
|
+
console.log('Agent recreated successfully');
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error('Failed to recreate agent:', error);
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
setupRoutes() {
|
|
80
|
+
this._app.get('/status', async (req, res)=>{
|
|
81
|
+
res.send({
|
|
82
|
+
status: 'ok',
|
|
83
|
+
id: this.id
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
this._app.get('/context/:uuid', async (req, res)=>{
|
|
87
|
+
const { uuid } = req.params;
|
|
88
|
+
const contextFile = this.filePathForUuid(uuid);
|
|
89
|
+
if (!existsSync(contextFile)) return res.status(404).json({
|
|
90
|
+
error: 'Context not found'
|
|
91
|
+
});
|
|
92
|
+
const context = readFileSync(contextFile, 'utf8');
|
|
93
|
+
res.json({
|
|
94
|
+
context
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
this._app.get('/task-progress/:requestId', async (req, res)=>{
|
|
98
|
+
const { requestId } = req.params;
|
|
99
|
+
res.json({
|
|
100
|
+
tip: this.taskProgressTips[requestId] || ''
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
this._app.post('/action-space', async (req, res)=>{
|
|
104
|
+
try {
|
|
105
|
+
let actionSpace = [];
|
|
106
|
+
actionSpace = await this.agent.interface.actionSpace();
|
|
107
|
+
const processedActionSpace = actionSpace.map((action)=>{
|
|
108
|
+
if (action && 'object' == typeof action && 'paramSchema' in action) {
|
|
109
|
+
const typedAction = action;
|
|
110
|
+
if (typedAction.paramSchema && 'object' == typeof typedAction.paramSchema) {
|
|
111
|
+
let processedSchema = null;
|
|
112
|
+
try {
|
|
113
|
+
if (typedAction.paramSchema.shape && 'object' == typeof typedAction.paramSchema.shape) processedSchema = {
|
|
114
|
+
type: 'ZodObject',
|
|
115
|
+
shape: typedAction.paramSchema.shape
|
|
116
|
+
};
|
|
117
|
+
} catch (e) {
|
|
118
|
+
const actionName = 'name' in typedAction && 'string' == typeof typedAction.name ? typedAction.name : 'unknown';
|
|
119
|
+
console.warn('Failed to process paramSchema for action:', actionName, e);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
...typedAction,
|
|
123
|
+
paramSchema: processedSchema
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return action;
|
|
128
|
+
});
|
|
129
|
+
res.json(processedActionSpace);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
132
|
+
console.error('Failed to get action space:', error);
|
|
133
|
+
res.status(500).json({
|
|
134
|
+
error: errorMessage
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
this._app.post('/playground-with-context', async (req, res)=>{
|
|
139
|
+
const context = req.body.context;
|
|
140
|
+
if (!context) return res.status(400).json({
|
|
141
|
+
error: 'context is required'
|
|
142
|
+
});
|
|
143
|
+
const requestId = utils_uuid();
|
|
144
|
+
this.saveContextFile(requestId, context);
|
|
145
|
+
return res.json({
|
|
146
|
+
location: `/playground/${requestId}`,
|
|
147
|
+
uuid: requestId
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
this._app.post('/execute', async (req, res)=>{
|
|
151
|
+
const { type, prompt, params, requestId, deepThink, screenshotIncluded, domIncluded } = req.body;
|
|
152
|
+
if (!type) return res.status(400).json({
|
|
153
|
+
error: 'type is required'
|
|
154
|
+
});
|
|
155
|
+
if (this.currentTaskId) return res.status(409).json({
|
|
156
|
+
error: 'Another task is already running',
|
|
157
|
+
currentTaskId: this.currentTaskId
|
|
158
|
+
});
|
|
159
|
+
if (requestId) {
|
|
160
|
+
this.currentTaskId = requestId;
|
|
161
|
+
this.taskProgressTips[requestId] = '';
|
|
162
|
+
this.agent.onTaskStartTip = (tip)=>{
|
|
163
|
+
this.taskProgressTips[requestId] = tip;
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const response = {
|
|
167
|
+
result: null,
|
|
168
|
+
dump: null,
|
|
169
|
+
error: null,
|
|
170
|
+
reportHTML: null,
|
|
171
|
+
requestId
|
|
172
|
+
};
|
|
173
|
+
const startTime = Date.now();
|
|
174
|
+
try {
|
|
175
|
+
const actionSpace = await this.agent.interface.actionSpace();
|
|
176
|
+
const value = {
|
|
177
|
+
type,
|
|
178
|
+
prompt,
|
|
179
|
+
params
|
|
180
|
+
};
|
|
181
|
+
response.result = await executeAction(this.agent, type, actionSpace, value, {
|
|
182
|
+
deepThink,
|
|
183
|
+
screenshotIncluded,
|
|
184
|
+
domIncluded
|
|
185
|
+
});
|
|
186
|
+
} catch (error) {
|
|
187
|
+
response.error = formatErrorMessage(error);
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
response.dump = JSON.parse(this.agent.dumpDataString());
|
|
191
|
+
response.reportHTML = this.agent.reportHTMLString() || null;
|
|
192
|
+
this.agent.writeOutActionDumps();
|
|
193
|
+
this.agent.resetDump();
|
|
194
|
+
} catch (error) {
|
|
195
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
196
|
+
console.error(`write out dump failed: requestId: ${requestId}, ${errorMessage}`);
|
|
197
|
+
}
|
|
198
|
+
res.send(response);
|
|
199
|
+
const timeCost = Date.now() - startTime;
|
|
200
|
+
if (response.error) console.error(`handle request failed after ${timeCost}ms: requestId: ${requestId}, ${response.error}`);
|
|
201
|
+
else console.log(`handle request done after ${timeCost}ms: requestId: ${requestId}`);
|
|
202
|
+
if (requestId) {
|
|
203
|
+
delete this.taskProgressTips[requestId];
|
|
204
|
+
if (this.currentTaskId === requestId) this.currentTaskId = null;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
this._app.post('/cancel/:requestId', async (req, res)=>{
|
|
208
|
+
const { requestId } = req.params;
|
|
209
|
+
if (!requestId) return res.status(400).json({
|
|
210
|
+
error: 'requestId is required'
|
|
211
|
+
});
|
|
212
|
+
try {
|
|
213
|
+
if (this.currentTaskId !== requestId) return res.json({
|
|
214
|
+
status: 'not_found',
|
|
215
|
+
message: 'Task not found or already completed'
|
|
216
|
+
});
|
|
217
|
+
console.log(`Cancelling task: ${requestId}`);
|
|
218
|
+
await this.recreateAgent();
|
|
219
|
+
delete this.taskProgressTips[requestId];
|
|
220
|
+
this.currentTaskId = null;
|
|
221
|
+
res.json({
|
|
222
|
+
status: 'cancelled',
|
|
223
|
+
message: 'Task cancelled successfully by recreating agent'
|
|
224
|
+
});
|
|
225
|
+
} catch (error) {
|
|
226
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
227
|
+
console.error(`Failed to cancel: ${errorMessage}`);
|
|
228
|
+
res.status(500).json({
|
|
229
|
+
error: `Failed to cancel: ${errorMessage}`
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
this._app.get('/screenshot', async (_req, res)=>{
|
|
234
|
+
try {
|
|
235
|
+
if ('function' != typeof this.agent.interface.screenshotBase64) return res.status(500).json({
|
|
236
|
+
error: 'Screenshot method not available on current interface'
|
|
237
|
+
});
|
|
238
|
+
const base64Screenshot = await this.agent.interface.screenshotBase64();
|
|
239
|
+
res.json({
|
|
240
|
+
screenshot: base64Screenshot,
|
|
241
|
+
timestamp: Date.now()
|
|
242
|
+
});
|
|
243
|
+
} catch (error) {
|
|
244
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
245
|
+
console.error(`Failed to take screenshot: ${errorMessage}`);
|
|
246
|
+
res.status(500).json({
|
|
247
|
+
error: `Failed to take screenshot: ${errorMessage}`
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
this._app.get('/interface-info', async (_req, res)=>{
|
|
252
|
+
try {
|
|
253
|
+
var _this_agent_interface_describe, _this_agent_interface;
|
|
254
|
+
const type = this.agent.interface.interfaceType || 'Unknown';
|
|
255
|
+
const description = (null == (_this_agent_interface_describe = (_this_agent_interface = this.agent.interface).describe) ? void 0 : _this_agent_interface_describe.call(_this_agent_interface)) || void 0;
|
|
256
|
+
res.json({
|
|
257
|
+
type,
|
|
258
|
+
description
|
|
259
|
+
});
|
|
260
|
+
} catch (error) {
|
|
261
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
262
|
+
console.error(`Failed to get interface info: ${errorMessage}`);
|
|
263
|
+
res.status(500).json({
|
|
264
|
+
error: `Failed to get interface info: ${errorMessage}`
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
this.app.post('/config', async (req, res)=>{
|
|
269
|
+
const { aiConfig } = req.body;
|
|
270
|
+
if (!aiConfig || 'object' != typeof aiConfig) return res.status(400).json({
|
|
271
|
+
error: 'aiConfig is required and must be an object'
|
|
272
|
+
});
|
|
273
|
+
if (0 === Object.keys(aiConfig).length) return res.json({
|
|
274
|
+
status: 'ok',
|
|
275
|
+
message: 'AI config not changed due to empty object'
|
|
276
|
+
});
|
|
277
|
+
try {
|
|
278
|
+
overrideAIConfig(aiConfig);
|
|
279
|
+
return res.json({
|
|
280
|
+
status: 'ok',
|
|
281
|
+
message: 'AI config updated successfully'
|
|
282
|
+
});
|
|
283
|
+
} catch (error) {
|
|
284
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
285
|
+
console.error(`Failed to update AI config: ${errorMessage}`);
|
|
286
|
+
return res.status(500).json({
|
|
287
|
+
error: `Failed to update AI config: ${errorMessage}`
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
setupStaticRoutes() {
|
|
293
|
+
this._app.get('/', (_req, res)=>{
|
|
294
|
+
this.serveHtmlWithPorts(res);
|
|
295
|
+
});
|
|
296
|
+
this._app.get('/index.html', (_req, res)=>{
|
|
297
|
+
this.serveHtmlWithPorts(res);
|
|
298
|
+
});
|
|
299
|
+
this._app.use(express["static"](this.staticPath));
|
|
300
|
+
this._app.get('*', (_req, res)=>{
|
|
301
|
+
this.serveHtmlWithPorts(res);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
serveHtmlWithPorts(res) {
|
|
305
|
+
try {
|
|
306
|
+
const htmlPath = join(this.staticPath, 'index.html');
|
|
307
|
+
let html = readFileSync(htmlPath, 'utf8');
|
|
308
|
+
const scrcpyPort = global.scrcpyServerPort || this.port + 1;
|
|
309
|
+
const configScript = `
|
|
310
|
+
<script>
|
|
311
|
+
window.SCRCPY_PORT = ${scrcpyPort};
|
|
312
|
+
</script>
|
|
313
|
+
`;
|
|
314
|
+
html = html.replace('</head>', `${configScript}</head>`);
|
|
315
|
+
res.setHeader('Content-Type', 'text/html');
|
|
316
|
+
res.send(html);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.error('Error serving HTML with ports:', error);
|
|
319
|
+
res.status(500).send('Internal Server Error');
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
async launch(port) {
|
|
323
|
+
if (this.agentFactory) {
|
|
324
|
+
console.log('Initializing agent from factory function...');
|
|
325
|
+
this.agent = await this.agentFactory();
|
|
326
|
+
console.log('Agent initialized successfully');
|
|
327
|
+
}
|
|
328
|
+
this.initializeApp();
|
|
329
|
+
this.port = port || defaultPort;
|
|
330
|
+
return new Promise((resolve)=>{
|
|
331
|
+
const serverPort = this.port;
|
|
332
|
+
this.server = this._app.listen(serverPort, ()=>{
|
|
333
|
+
resolve(this);
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
async close() {
|
|
338
|
+
return new Promise((resolve, reject)=>{
|
|
339
|
+
if (this.server) {
|
|
340
|
+
try {
|
|
341
|
+
this.agent.destroy();
|
|
342
|
+
} catch (error) {
|
|
343
|
+
console.warn('Failed to destroy agent:', error);
|
|
344
|
+
}
|
|
345
|
+
this.taskProgressTips = {};
|
|
346
|
+
this.server.close((error)=>{
|
|
347
|
+
if (error) reject(error);
|
|
348
|
+
else {
|
|
349
|
+
this.server = void 0;
|
|
350
|
+
resolve();
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
} else resolve();
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
constructor(agent, staticPath = STATIC_PATH, id){
|
|
357
|
+
_define_property(this, "_app", void 0);
|
|
358
|
+
_define_property(this, "tmpDir", void 0);
|
|
359
|
+
_define_property(this, "server", void 0);
|
|
360
|
+
_define_property(this, "port", void 0);
|
|
361
|
+
_define_property(this, "agent", void 0);
|
|
362
|
+
_define_property(this, "staticPath", void 0);
|
|
363
|
+
_define_property(this, "taskProgressTips", void 0);
|
|
364
|
+
_define_property(this, "id", void 0);
|
|
365
|
+
_define_property(this, "_initialized", false);
|
|
366
|
+
_define_property(this, "agentFactory", void 0);
|
|
367
|
+
_define_property(this, "currentTaskId", null);
|
|
368
|
+
this._app = express();
|
|
369
|
+
this.tmpDir = getTmpDir();
|
|
370
|
+
this.staticPath = staticPath;
|
|
371
|
+
this.taskProgressTips = {};
|
|
372
|
+
this.id = id || utils_uuid();
|
|
373
|
+
if ('function' == typeof agent) {
|
|
374
|
+
this.agentFactory = agent;
|
|
375
|
+
this.agent = null;
|
|
376
|
+
} else {
|
|
377
|
+
this.agent = agent;
|
|
378
|
+
this.agentFactory = null;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const server = PlaygroundServer;
|
|
383
|
+
export { PlaygroundServer, server as default };
|
|
384
|
+
|
|
385
|
+
//# sourceMappingURL=server.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.mjs","sources":["webpack://@sqaitech/playground/./src/server.ts"],"sourcesContent":["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":["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","Object","overrideAIConfig","htmlPath","html","scrcpyPort","global","configScript","port","Promise","resolve","serverPort","reject","agent","staticPath","id","getTmpDir"],"mappings":"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"}
|
|
File without changes
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
BasePlaygroundAdapter: ()=>BasePlaygroundAdapter
|
|
28
|
+
});
|
|
29
|
+
const ai_model_namespaceObject = require("@sqaitech/core/ai-model");
|
|
30
|
+
class BasePlaygroundAdapter {
|
|
31
|
+
async getActionSpace(_context) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
validateParams(value, action) {
|
|
35
|
+
if (!(null == action ? void 0 : action.paramSchema)) return {
|
|
36
|
+
valid: true
|
|
37
|
+
};
|
|
38
|
+
const needsStructuredParams = this.actionNeedsStructuredParams(action);
|
|
39
|
+
if (!needsStructuredParams) return {
|
|
40
|
+
valid: true
|
|
41
|
+
};
|
|
42
|
+
if (!value.params) return {
|
|
43
|
+
valid: false,
|
|
44
|
+
errorMessage: 'Parameters are required'
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
const paramsForValidation = this.prepareParamsForValidation(value.params, action);
|
|
48
|
+
action.paramSchema.parse(paramsForValidation);
|
|
49
|
+
return {
|
|
50
|
+
valid: true
|
|
51
|
+
};
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return this.handleValidationError(error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
createDisplayContent(value, needsStructuredParams, action) {
|
|
57
|
+
if (!needsStructuredParams || !value.params || !(null == action ? void 0 : action.paramSchema)) return value.prompt || '';
|
|
58
|
+
const paramsList = this.buildParamsDisplayList(value.params, action);
|
|
59
|
+
return paramsList.join('\n') || value.prompt || '';
|
|
60
|
+
}
|
|
61
|
+
formatBasicErrorMessage(error) {
|
|
62
|
+
return (null == error ? void 0 : error.message) || 'Unknown error';
|
|
63
|
+
}
|
|
64
|
+
getSchemaKeys(action) {
|
|
65
|
+
if (!(null == action ? void 0 : action.paramSchema) || !('shape' in action.paramSchema)) return [];
|
|
66
|
+
const schema = action.paramSchema;
|
|
67
|
+
return schema && 'shape' in schema ? Object.keys(schema.shape) : [];
|
|
68
|
+
}
|
|
69
|
+
filterValidParams(params, excludeKeys = []) {
|
|
70
|
+
const filtered = {};
|
|
71
|
+
Object.keys(params).forEach((key)=>{
|
|
72
|
+
if (!excludeKeys.includes(key) && void 0 !== params[key] && null !== params[key] && '' !== params[key]) filtered[key] = params[key];
|
|
73
|
+
});
|
|
74
|
+
return filtered;
|
|
75
|
+
}
|
|
76
|
+
actionNeedsStructuredParams(action) {
|
|
77
|
+
if ('object' == typeof action.paramSchema && 'shape' in action.paramSchema) {
|
|
78
|
+
const shape = action.paramSchema.shape || {};
|
|
79
|
+
return Object.keys(shape).length > 0;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
prepareParamsForValidation(params, action) {
|
|
84
|
+
const paramsForValidation = {
|
|
85
|
+
...params
|
|
86
|
+
};
|
|
87
|
+
if (action.paramSchema) {
|
|
88
|
+
const locatorFieldKeys = (0, ai_model_namespaceObject.findAllMidsceneLocatorField)(action.paramSchema);
|
|
89
|
+
locatorFieldKeys.forEach((key)=>{
|
|
90
|
+
if ('string' == typeof paramsForValidation[key]) paramsForValidation[key] = {
|
|
91
|
+
midscene_location_field_flag: true,
|
|
92
|
+
prompt: paramsForValidation[key],
|
|
93
|
+
center: [
|
|
94
|
+
0,
|
|
95
|
+
0
|
|
96
|
+
],
|
|
97
|
+
rect: {
|
|
98
|
+
left: 0,
|
|
99
|
+
top: 0,
|
|
100
|
+
width: 0,
|
|
101
|
+
height: 0
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return paramsForValidation;
|
|
107
|
+
}
|
|
108
|
+
handleValidationError(error) {
|
|
109
|
+
const zodError = error;
|
|
110
|
+
if (zodError.errors && zodError.errors.length > 0) {
|
|
111
|
+
const errorMessages = zodError.errors.filter((err)=>{
|
|
112
|
+
const path = err.path.join('.');
|
|
113
|
+
return !path.includes('center') && !path.includes('rect') && !path.includes('midscene_location_field_flag');
|
|
114
|
+
}).map((err)=>{
|
|
115
|
+
const field = err.path.join('.');
|
|
116
|
+
return `${field}: ${err.message}`;
|
|
117
|
+
});
|
|
118
|
+
if (errorMessages.length > 0) return {
|
|
119
|
+
valid: false,
|
|
120
|
+
errorMessage: `Validation error: ${errorMessages.join(', ')}`
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const errorMsg = error instanceof Error ? error.message : 'Unknown validation error';
|
|
124
|
+
return {
|
|
125
|
+
valid: false,
|
|
126
|
+
errorMessage: `Parameter validation failed: ${errorMsg}`
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
buildParamsDisplayList(params, action) {
|
|
130
|
+
const paramsList = [];
|
|
131
|
+
const schema = action.paramSchema;
|
|
132
|
+
if (!(schema && 'shape' in schema)) return paramsList;
|
|
133
|
+
const locatorFieldKeys = (0, ai_model_namespaceObject.findAllMidsceneLocatorField)(schema);
|
|
134
|
+
const shapeKeys = Object.keys(schema.shape);
|
|
135
|
+
shapeKeys.forEach((key)=>{
|
|
136
|
+
const paramValue = params[key];
|
|
137
|
+
if (this.isValidParamValue(paramValue)) {
|
|
138
|
+
const displayKey = this.capitalizeFirstLetter(key);
|
|
139
|
+
const formattedValue = this.formatParamValue(key, paramValue, locatorFieldKeys.includes(key));
|
|
140
|
+
paramsList.push(`${displayKey}: ${formattedValue}`);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
return paramsList;
|
|
144
|
+
}
|
|
145
|
+
isValidParamValue(value) {
|
|
146
|
+
return null != value && '' !== value;
|
|
147
|
+
}
|
|
148
|
+
capitalizeFirstLetter(str) {
|
|
149
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
150
|
+
}
|
|
151
|
+
formatParamValue(key, value, isLocateField) {
|
|
152
|
+
if (isLocateField || 'string' == typeof value) return `"${value}"`;
|
|
153
|
+
if ('number' == typeof value) return 'distance' === key ? `${value}px` : `${value}`;
|
|
154
|
+
return `${value}`;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.BasePlaygroundAdapter = __webpack_exports__.BasePlaygroundAdapter;
|
|
158
|
+
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
159
|
+
"BasePlaygroundAdapter"
|
|
160
|
+
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
161
|
+
Object.defineProperty(exports, '__esModule', {
|
|
162
|
+
value: true
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters\\base.js","sources":["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/adapters/base.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { DeviceAction } from '@sqaitech/core';\r\nimport { findAllMidsceneLocatorField } from '@sqaitech/core/ai-model';\r\nimport type { ExecutionOptions, FormValue, ValidationResult } from '../types';\r\n\r\nexport abstract class BasePlaygroundAdapter {\r\n abstract parseStructuredParams(\r\n action: DeviceAction<unknown>,\r\n params: Record<string, unknown>,\r\n options: ExecutionOptions,\r\n ): Promise<unknown[]>;\r\n\r\n abstract formatErrorMessage(error: any): string;\r\n\r\n // Abstract method for execution - must be implemented by concrete adapters\r\n abstract executeAction(\r\n actionType: string,\r\n value: FormValue,\r\n options: ExecutionOptions,\r\n ): Promise<unknown>;\r\n\r\n // Optional method for getting action space - default implementation returns empty array\r\n async getActionSpace(_context: any): Promise<DeviceAction<unknown>[]> {\r\n return [];\r\n }\r\n\r\n // Common validation logic - can be overridden if needed\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 try {\r\n const paramsForValidation = this.prepareParamsForValidation(\r\n value.params,\r\n action,\r\n );\r\n action.paramSchema.parse(paramsForValidation);\r\n return { valid: true };\r\n } catch (error: unknown) {\r\n return this.handleValidationError(error);\r\n }\r\n }\r\n\r\n // Common display content creation logic - can be overridden if needed\r\n createDisplayContent(\r\n value: FormValue,\r\n needsStructuredParams: boolean,\r\n action: DeviceAction<unknown> | undefined,\r\n ): string {\r\n if (!needsStructuredParams || !value.params || !action?.paramSchema) {\r\n return value.prompt || '';\r\n }\r\n\r\n const paramsList = this.buildParamsDisplayList(value.params, action);\r\n return paramsList.join('\\n') || value.prompt || '';\r\n }\r\n\r\n // Helper method for basic error message formatting\r\n protected formatBasicErrorMessage(error: any): string {\r\n return error?.message || 'Unknown error';\r\n }\r\n\r\n // Helper method for parsing structured params base logic\r\n protected getSchemaKeys(action: DeviceAction<unknown>): string[] {\r\n if (!action?.paramSchema || !('shape' in action.paramSchema)) {\r\n return [];\r\n }\r\n\r\n const schema = action.paramSchema;\r\n return schema && 'shape' in schema\r\n ? Object.keys((schema as { shape: Record<string, unknown> }).shape)\r\n : [];\r\n }\r\n\r\n // Helper method for filtering valid params\r\n protected filterValidParams(\r\n params: Record<string, unknown>,\r\n excludeKeys: string[] = [],\r\n ): Record<string, unknown> {\r\n const filtered: Record<string, unknown> = {};\r\n\r\n Object.keys(params).forEach((key) => {\r\n if (\r\n !excludeKeys.includes(key) &&\r\n params[key] !== undefined &&\r\n params[key] !== null &&\r\n params[key] !== ''\r\n ) {\r\n filtered[key] = params[key];\r\n }\r\n });\r\n\r\n return filtered;\r\n }\r\n\r\n // Check if action needs structured parameters\r\n protected actionNeedsStructuredParams(\r\n action: DeviceAction<unknown>,\r\n ): boolean {\r\n if (\r\n typeof action.paramSchema === 'object' &&\r\n 'shape' in action.paramSchema\r\n ) {\r\n const shape =\r\n (action.paramSchema as { shape: Record<string, unknown> }).shape || {};\r\n return Object.keys(shape).length > 0;\r\n }\r\n return true; // If paramSchema exists but not in expected format, assume it needs params\r\n }\r\n\r\n // Prepare parameters for validation by converting string locate fields\r\n protected prepareParamsForValidation(\r\n params: Record<string, unknown>,\r\n action: DeviceAction<unknown>,\r\n ): Record<string, unknown> {\r\n const paramsForValidation = { ...params };\r\n\r\n if (action.paramSchema) {\r\n const locatorFieldKeys = findAllMidsceneLocatorField(action.paramSchema);\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], // dummy values for validation\r\n rect: { left: 0, top: 0, width: 0, height: 0 },\r\n };\r\n }\r\n });\r\n }\r\n\r\n return paramsForValidation;\r\n }\r\n\r\n // Handle validation errors with proper error message extraction\r\n protected handleValidationError(error: unknown): ValidationResult {\r\n const zodError = error as {\r\n errors?: Array<{ path: string[]; message: string }>;\r\n };\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 }\r\n\r\n const errorMsg =\r\n error instanceof Error ? error.message : 'Unknown validation error';\r\n\r\n return {\r\n valid: false,\r\n errorMessage: `Parameter validation failed: ${errorMsg}`,\r\n };\r\n }\r\n\r\n // Build display list for parameters\r\n protected buildParamsDisplayList(\r\n params: Record<string, unknown>,\r\n action: DeviceAction<unknown>,\r\n ): string[] {\r\n const paramsList: string[] = [];\r\n const schema = action.paramSchema;\r\n\r\n if (!(schema && 'shape' in schema)) {\r\n return paramsList;\r\n }\r\n\r\n const locatorFieldKeys = findAllMidsceneLocatorField(schema);\r\n const shapeKeys = Object.keys(\r\n (schema as { shape: Record<string, unknown> }).shape,\r\n );\r\n\r\n shapeKeys.forEach((key) => {\r\n const paramValue = params[key];\r\n if (this.isValidParamValue(paramValue)) {\r\n const displayKey = this.capitalizeFirstLetter(key);\r\n const formattedValue = this.formatParamValue(\r\n key,\r\n paramValue,\r\n locatorFieldKeys.includes(key),\r\n );\r\n paramsList.push(`${displayKey}: ${formattedValue}`);\r\n }\r\n });\r\n\r\n return paramsList;\r\n }\r\n\r\n // Check if parameter value is valid for display\r\n protected isValidParamValue(value: unknown): boolean {\r\n return value !== undefined && value !== null && value !== '';\r\n }\r\n\r\n // Capitalize first letter of a string\r\n protected capitalizeFirstLetter(str: string): string {\r\n return str.charAt(0).toUpperCase() + str.slice(1);\r\n }\r\n\r\n // Format parameter value for display\r\n protected formatParamValue(\r\n key: string,\r\n value: unknown,\r\n isLocateField: boolean,\r\n ): string {\r\n if (isLocateField || typeof value === 'string') {\r\n return `\"${value}\"`;\r\n }\r\n\r\n if (typeof value === 'number') {\r\n // Special handling for distance in scroll\r\n return key === 'distance' ? `${value}px` : `${value}`;\r\n }\r\n\r\n return `${value}`;\r\n }\r\n}\r\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","BasePlaygroundAdapter","_context","value","action","needsStructuredParams","paramsForValidation","error","paramsList","schema","params","excludeKeys","filtered","undefined","shape","locatorFieldKeys","findAllMidsceneLocatorField","zodError","errorMessages","err","path","field","errorMsg","Error","shapeKeys","paramValue","displayKey","formattedValue","str","isLocateField"],"mappings":"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"}
|