@midscene/playground 0.28.3 → 0.28.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/adapters/local-execution.mjs +40 -7
- package/dist/es/adapters/local-execution.mjs.map +1 -1
- package/dist/es/adapters/remote-execution.mjs +97 -7
- package/dist/es/adapters/remote-execution.mjs.map +1 -1
- package/dist/es/index.mjs +3 -2
- package/dist/es/launcher.mjs +89 -0
- package/dist/es/launcher.mjs.map +1 -0
- package/dist/es/sdk/index.mjs +26 -1
- package/dist/es/sdk/index.mjs.map +1 -1
- package/dist/es/server.mjs +137 -101
- package/dist/es/server.mjs.map +1 -1
- package/dist/lib/adapters/local-execution.js +40 -7
- package/dist/lib/adapters/local-execution.js.map +1 -1
- package/dist/lib/adapters/remote-execution.js +97 -7
- package/dist/lib/adapters/remote-execution.js.map +1 -1
- package/dist/lib/index.js +5 -11
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/launcher.js +133 -0
- package/dist/lib/launcher.js.map +1 -0
- package/dist/lib/sdk/index.js +26 -1
- package/dist/lib/sdk/index.js.map +1 -1
- package/dist/lib/server.js +142 -102
- package/dist/lib/server.js.map +1 -1
- package/dist/types/adapters/local-execution.d.ts +4 -2
- package/dist/types/adapters/remote-execution.d.ts +13 -3
- package/dist/types/index.d.ts +3 -1
- package/dist/types/launcher.d.ts +66 -0
- package/dist/types/sdk/index.d.ts +11 -1
- package/dist/types/server.d.ts +55 -9
- package/dist/types/types.d.ts +3 -10
- package/package.json +6 -6
- package/static/favicon.ico +0 -0
- package/static/index.html +1 -0
- package/static/static/css/index.12edce92.css +2 -0
- package/static/static/css/index.12edce92.css.map +1 -0
- package/static/static/js/345.c34b9bb0.js +673 -0
- package/static/static/js/345.c34b9bb0.js.LICENSE.txt +157 -0
- package/static/static/js/345.c34b9bb0.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/290.dd04c2bc.js +21 -0
- package/static/static/js/async/290.dd04c2bc.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/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.77b067da.js +21 -0
- package/static/static/js/index.77b067da.js.LICENSE.txt +7 -0
- package/static/static/js/index.77b067da.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/wasm/9e906fbf55e08f98.module.wasm +0 -0
- package/LICENSE +0 -21
package/dist/es/server.mjs
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { getTmpDir } from "@midscene/core/utils";
|
|
5
6
|
import { PLAYGROUND_SERVER_PORT } from "@midscene/shared/constants";
|
|
6
7
|
import { overrideAIConfig } from "@midscene/shared/env";
|
|
7
|
-
import { ifInBrowser, ifInWorker } from "@midscene/shared/utils";
|
|
8
|
-
import cors from "cors";
|
|
9
|
-
import dotenv from "dotenv";
|
|
10
8
|
import express from "express";
|
|
11
9
|
import { executeAction, formatErrorMessage } from "./common.mjs";
|
|
10
|
+
import "dotenv/config";
|
|
12
11
|
function _define_property(obj, key, value) {
|
|
13
12
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
14
13
|
value: value,
|
|
@@ -20,16 +19,38 @@ function _define_property(obj, key, value) {
|
|
|
20
19
|
return obj;
|
|
21
20
|
}
|
|
22
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');
|
|
23
25
|
const errorHandler = (err, req, res, next)=>{
|
|
24
26
|
console.error(err);
|
|
27
|
+
const errorMessage = err instanceof Error ? err.message : 'Internal server error';
|
|
25
28
|
res.status(500).json({
|
|
26
|
-
error:
|
|
29
|
+
error: errorMessage
|
|
27
30
|
});
|
|
28
31
|
};
|
|
29
|
-
const setup = async ()=>{
|
|
30
|
-
if (!ifInBrowser && !ifInWorker) dotenv.config();
|
|
31
|
-
};
|
|
32
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.page && 'function' == typeof this.page.updateContext) {
|
|
44
|
+
this.page.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
|
+
}
|
|
33
54
|
filePathForUuid(uuid) {
|
|
34
55
|
return join(this.tmpDir, `${uuid}.json`);
|
|
35
56
|
}
|
|
@@ -39,19 +60,13 @@ class PlaygroundServer {
|
|
|
39
60
|
writeFileSync(tmpFile, context);
|
|
40
61
|
return tmpFile;
|
|
41
62
|
}
|
|
42
|
-
|
|
43
|
-
this.
|
|
44
|
-
this.app.use(errorHandler);
|
|
45
|
-
this.app.use(cors({
|
|
46
|
-
origin: '*',
|
|
47
|
-
credentials: true
|
|
48
|
-
}));
|
|
49
|
-
this.app.get('/status', async (req, res)=>{
|
|
63
|
+
setupRoutes() {
|
|
64
|
+
this._app.get('/status', async (req, res)=>{
|
|
50
65
|
res.send({
|
|
51
66
|
status: 'ok'
|
|
52
67
|
});
|
|
53
68
|
});
|
|
54
|
-
this.
|
|
69
|
+
this._app.get('/context/:uuid', async (req, res)=>{
|
|
55
70
|
const { uuid } = req.params;
|
|
56
71
|
const contextFile = this.filePathForUuid(uuid);
|
|
57
72
|
if (!existsSync(contextFile)) return res.status(404).json({
|
|
@@ -62,51 +77,48 @@ class PlaygroundServer {
|
|
|
62
77
|
context
|
|
63
78
|
});
|
|
64
79
|
});
|
|
65
|
-
this.
|
|
80
|
+
this._app.get('/task-progress/:requestId', async (req, res)=>{
|
|
66
81
|
const { requestId } = req.params;
|
|
67
82
|
res.json({
|
|
68
83
|
tip: this.taskProgressTips[requestId] || ''
|
|
69
84
|
});
|
|
70
85
|
});
|
|
71
|
-
this.
|
|
72
|
-
limit: '30mb'
|
|
73
|
-
}), async (req, res)=>{
|
|
74
|
-
const { context } = req.body;
|
|
75
|
-
if (!context) return res.status(400).json({
|
|
76
|
-
error: 'context is required'
|
|
77
|
-
});
|
|
86
|
+
this._app.post('/action-space', async (req, res)=>{
|
|
78
87
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
let actionSpace = [];
|
|
89
|
+
actionSpace = await this.page.actionSpace();
|
|
81
90
|
const processedActionSpace = actionSpace.map((action)=>{
|
|
82
|
-
if (action
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
shape
|
|
91
|
+
if (action && 'object' == typeof action && 'paramSchema' in action) {
|
|
92
|
+
const typedAction = action;
|
|
93
|
+
if (typedAction.paramSchema && 'object' == typeof typedAction.paramSchema) {
|
|
94
|
+
let processedSchema = null;
|
|
95
|
+
try {
|
|
96
|
+
if (typedAction.paramSchema.shape && 'object' == typeof typedAction.paramSchema.shape) processedSchema = {
|
|
97
|
+
type: 'ZodObject',
|
|
98
|
+
shape: typedAction.paramSchema.shape
|
|
99
|
+
};
|
|
100
|
+
} catch (e) {
|
|
101
|
+
const actionName = 'name' in typedAction && 'string' == typeof typedAction.name ? typedAction.name : 'unknown';
|
|
102
|
+
console.warn('Failed to process paramSchema for action:', actionName, e);
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...typedAction,
|
|
106
|
+
paramSchema: processedSchema
|
|
88
107
|
};
|
|
89
|
-
} catch (e) {
|
|
90
|
-
console.warn('Failed to process paramSchema for action:', action.name, e);
|
|
91
108
|
}
|
|
92
|
-
return {
|
|
93
|
-
...action,
|
|
94
|
-
paramSchema: processedSchema
|
|
95
|
-
};
|
|
96
109
|
}
|
|
97
110
|
return action;
|
|
98
111
|
});
|
|
99
112
|
res.json(processedActionSpace);
|
|
100
113
|
} catch (error) {
|
|
114
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
101
115
|
console.error('Failed to get action space:', error);
|
|
102
116
|
res.status(500).json({
|
|
103
|
-
error:
|
|
117
|
+
error: errorMessage
|
|
104
118
|
});
|
|
105
119
|
}
|
|
106
120
|
});
|
|
107
|
-
this.
|
|
108
|
-
limit: '50mb'
|
|
109
|
-
}), async (req, res)=>{
|
|
121
|
+
this._app.post('/playground-with-context', async (req, res)=>{
|
|
110
122
|
const context = req.body.context;
|
|
111
123
|
if (!context) return res.status(400).json({
|
|
112
124
|
error: 'context is required'
|
|
@@ -118,22 +130,14 @@ class PlaygroundServer {
|
|
|
118
130
|
uuid
|
|
119
131
|
});
|
|
120
132
|
});
|
|
121
|
-
this.
|
|
122
|
-
|
|
123
|
-
}), async (req, res)=>{
|
|
124
|
-
const { context, type, prompt, params, requestId, deepThink, screenshotIncluded, domIncluded } = req.body;
|
|
125
|
-
if (!context) return res.status(400).json({
|
|
126
|
-
error: 'context is required'
|
|
127
|
-
});
|
|
133
|
+
this._app.post('/execute', async (req, res)=>{
|
|
134
|
+
const { type, prompt, params, requestId, deepThink, screenshotIncluded, domIncluded } = req.body;
|
|
128
135
|
if (!type) return res.status(400).json({
|
|
129
136
|
error: 'type is required'
|
|
130
137
|
});
|
|
131
|
-
const page = new this.pageClass(context);
|
|
132
|
-
const agent = new this.agentClass(page);
|
|
133
138
|
if (requestId) {
|
|
134
139
|
this.taskProgressTips[requestId] = '';
|
|
135
|
-
this.
|
|
136
|
-
agent.onTaskStartTip = (tip)=>{
|
|
140
|
+
this.agent.onTaskStartTip = (tip)=>{
|
|
137
141
|
this.taskProgressTips[requestId] = tip;
|
|
138
142
|
};
|
|
139
143
|
}
|
|
@@ -146,13 +150,13 @@ class PlaygroundServer {
|
|
|
146
150
|
};
|
|
147
151
|
const startTime = Date.now();
|
|
148
152
|
try {
|
|
149
|
-
const actionSpace = await page.actionSpace();
|
|
153
|
+
const actionSpace = await this.page.actionSpace();
|
|
150
154
|
const value = {
|
|
151
155
|
type,
|
|
152
156
|
prompt,
|
|
153
157
|
params
|
|
154
158
|
};
|
|
155
|
-
response.result = await executeAction(agent, type, actionSpace, value, {
|
|
159
|
+
response.result = await executeAction(this.agent, type, actionSpace, value, {
|
|
156
160
|
deepThink: deepThink || false,
|
|
157
161
|
screenshotIncluded,
|
|
158
162
|
domIncluded
|
|
@@ -161,44 +165,57 @@ class PlaygroundServer {
|
|
|
161
165
|
response.error = formatErrorMessage(error);
|
|
162
166
|
}
|
|
163
167
|
try {
|
|
164
|
-
response.dump = JSON.parse(agent.dumpDataString());
|
|
165
|
-
response.reportHTML = agent.reportHTMLString() || null;
|
|
166
|
-
agent.writeOutActionDumps();
|
|
167
|
-
agent.
|
|
168
|
+
response.dump = JSON.parse(this.agent.dumpDataString());
|
|
169
|
+
response.reportHTML = this.agent.reportHTMLString() || null;
|
|
170
|
+
this.agent.writeOutActionDumps();
|
|
171
|
+
this.agent.resetDump();
|
|
168
172
|
} catch (error) {
|
|
169
|
-
|
|
173
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
174
|
+
console.error(`write out dump failed: requestId: ${requestId}, ${errorMessage}`);
|
|
170
175
|
}
|
|
171
176
|
res.send(response);
|
|
172
177
|
const timeCost = Date.now() - startTime;
|
|
173
178
|
if (response.error) console.error(`handle request failed after ${timeCost}ms: requestId: ${requestId}, ${response.error}`);
|
|
174
179
|
else console.log(`handle request done after ${timeCost}ms: requestId: ${requestId}`);
|
|
175
|
-
if (requestId
|
|
180
|
+
if (requestId) delete this.taskProgressTips[requestId];
|
|
176
181
|
});
|
|
177
|
-
this.
|
|
182
|
+
this._app.post('/cancel/:requestId', async (req, res)=>{
|
|
178
183
|
const { requestId } = req.params;
|
|
179
184
|
if (!requestId) return res.status(400).json({
|
|
180
185
|
error: 'requestId is required'
|
|
181
186
|
});
|
|
182
|
-
const agent = this.activeAgents[requestId];
|
|
183
|
-
if (!agent) return res.status(404).json({
|
|
184
|
-
error: 'No active agent found for this requestId'
|
|
185
|
-
});
|
|
186
187
|
try {
|
|
187
|
-
|
|
188
|
-
delete this.activeAgents[requestId];
|
|
188
|
+
if (this.taskProgressTips[requestId]) delete this.taskProgressTips[requestId];
|
|
189
189
|
res.json({
|
|
190
190
|
status: 'cancelled'
|
|
191
191
|
});
|
|
192
192
|
} catch (error) {
|
|
193
|
-
|
|
193
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
194
|
+
console.error(`Failed to cancel: ${errorMessage}`);
|
|
195
|
+
res.status(500).json({
|
|
196
|
+
error: `Failed to cancel: ${errorMessage}`
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
this._app.get('/screenshot', async (_req, res)=>{
|
|
201
|
+
try {
|
|
202
|
+
if ('function' != typeof this.page.screenshotBase64) return res.status(500).json({
|
|
203
|
+
error: 'Screenshot method not available on current interface'
|
|
204
|
+
});
|
|
205
|
+
const base64Screenshot = await this.page.screenshotBase64();
|
|
206
|
+
res.json({
|
|
207
|
+
screenshot: base64Screenshot,
|
|
208
|
+
timestamp: Date.now()
|
|
209
|
+
});
|
|
210
|
+
} catch (error) {
|
|
211
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
212
|
+
console.error(`Failed to take screenshot: ${errorMessage}`);
|
|
194
213
|
res.status(500).json({
|
|
195
|
-
error: `Failed to
|
|
214
|
+
error: `Failed to take screenshot: ${errorMessage}`
|
|
196
215
|
});
|
|
197
216
|
}
|
|
198
217
|
});
|
|
199
|
-
this.app.post('/config',
|
|
200
|
-
limit: '1mb'
|
|
201
|
-
}), async (req, res)=>{
|
|
218
|
+
this.app.post('/config', async (req, res)=>{
|
|
202
219
|
const { aiConfig } = req.body;
|
|
203
220
|
if (!aiConfig || 'object' != typeof aiConfig) return res.status(400).json({
|
|
204
221
|
error: 'aiConfig is required and must be an object'
|
|
@@ -210,52 +227,71 @@ class PlaygroundServer {
|
|
|
210
227
|
message: 'AI config updated successfully'
|
|
211
228
|
});
|
|
212
229
|
} catch (error) {
|
|
213
|
-
|
|
230
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
231
|
+
console.error(`Failed to update AI config: ${errorMessage}`);
|
|
214
232
|
return res.status(500).json({
|
|
215
|
-
error: `Failed to update AI config: ${
|
|
233
|
+
error: `Failed to update AI config: ${errorMessage}`
|
|
216
234
|
});
|
|
217
235
|
}
|
|
218
236
|
});
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
237
|
+
}
|
|
238
|
+
setupStaticRoutes() {
|
|
239
|
+
this._app.get('/', (_req, res)=>{
|
|
240
|
+
res.redirect('/index.html');
|
|
241
|
+
});
|
|
242
|
+
this._app.use(express["static"](this.staticPath));
|
|
243
|
+
this._app.get('*', (_req, res)=>{
|
|
244
|
+
res.sendFile(join(this.staticPath, 'index.html'));
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
async launch(port) {
|
|
248
|
+
this.initializeApp();
|
|
249
|
+
this.port = port || defaultPort;
|
|
229
250
|
return new Promise((resolve)=>{
|
|
230
|
-
const
|
|
231
|
-
this.server = this.
|
|
251
|
+
const serverPort = this.port;
|
|
252
|
+
this.server = this._app.listen(serverPort, ()=>{
|
|
232
253
|
resolve(this);
|
|
233
254
|
});
|
|
234
255
|
});
|
|
235
256
|
}
|
|
236
|
-
close() {
|
|
237
|
-
|
|
257
|
+
async close() {
|
|
258
|
+
return new Promise((resolve, reject)=>{
|
|
259
|
+
if (this.server) {
|
|
260
|
+
try {
|
|
261
|
+
this.agent.destroy();
|
|
262
|
+
} catch (error) {
|
|
263
|
+
console.warn('Failed to destroy agent:', error);
|
|
264
|
+
}
|
|
265
|
+
this.taskProgressTips = {};
|
|
266
|
+
this.server.close((error)=>{
|
|
267
|
+
if (error) reject(error);
|
|
268
|
+
else {
|
|
269
|
+
this.server = void 0;
|
|
270
|
+
resolve();
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
} else resolve();
|
|
274
|
+
});
|
|
238
275
|
}
|
|
239
|
-
constructor(
|
|
240
|
-
_define_property(this, "
|
|
276
|
+
constructor(page, agent, staticPath = STATIC_PATH){
|
|
277
|
+
_define_property(this, "_app", void 0);
|
|
241
278
|
_define_property(this, "tmpDir", void 0);
|
|
242
279
|
_define_property(this, "server", void 0);
|
|
243
280
|
_define_property(this, "port", void 0);
|
|
244
|
-
_define_property(this, "
|
|
245
|
-
_define_property(this, "
|
|
281
|
+
_define_property(this, "page", void 0);
|
|
282
|
+
_define_property(this, "agent", void 0);
|
|
246
283
|
_define_property(this, "staticPath", void 0);
|
|
247
284
|
_define_property(this, "taskProgressTips", void 0);
|
|
248
|
-
_define_property(this, "
|
|
249
|
-
this.
|
|
285
|
+
_define_property(this, "_initialized", false);
|
|
286
|
+
this._app = express();
|
|
250
287
|
this.tmpDir = getTmpDir();
|
|
251
|
-
this.
|
|
252
|
-
this.
|
|
288
|
+
this.page = page;
|
|
289
|
+
this.agent = agent;
|
|
253
290
|
this.staticPath = staticPath;
|
|
254
291
|
this.taskProgressTips = {};
|
|
255
|
-
this.activeAgents = {};
|
|
256
|
-
setup();
|
|
257
292
|
}
|
|
258
293
|
}
|
|
259
|
-
|
|
294
|
+
const server = PlaygroundServer;
|
|
295
|
+
export { PlaygroundServer, server as default };
|
|
260
296
|
|
|
261
297
|
//# sourceMappingURL=server.mjs.map
|
package/dist/es/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.mjs","sources":["webpack://@midscene/playground/./src/server.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport type { Server } from 'node:http';\nimport { join } from 'node:path';\nimport type { Agent as PageAgent } from '@midscene/core/agent';\nimport type { AbstractInterface } from '@midscene/core/device';\nimport { getTmpDir } from '@midscene/core/utils';\nimport { PLAYGROUND_SERVER_PORT } from '@midscene/shared/constants';\nimport { overrideAIConfig } from '@midscene/shared/env';\nimport { ifInBrowser, ifInWorker } from '@midscene/shared/utils';\nimport cors from 'cors';\nimport dotenv from 'dotenv';\nimport express, { type Request, type Response } from 'express';\nimport { executeAction, formatErrorMessage } from './common';\nimport type { PlaygroundAgent } from './types';\n\nconst defaultPort = PLAYGROUND_SERVER_PORT;\n\nconst errorHandler = (err: any, req: any, res: any, next: any) => {\n console.error(err);\n res.status(500).json({\n error: err.message,\n });\n};\n\nconst setup = async () => {\n if (!ifInBrowser && !ifInWorker) {\n dotenv.config();\n }\n};\n\nexport default class PlaygroundServer {\n app: express.Application;\n tmpDir: string;\n server?: Server;\n port?: number | null;\n pageClass: new (\n ...args: any[]\n ) => AbstractInterface;\n agentClass: new (\n ...args: any[]\n ) => PageAgent;\n staticPath?: string;\n taskProgressTips: Record<string, string>;\n activeAgents: Record<string, PageAgent>;\n\n constructor(\n pageClass: new (...args: any[]) => AbstractInterface,\n agentClass: new (...args: any[]) => PageAgent,\n staticPath?: string,\n ) {\n this.app = express();\n this.tmpDir = getTmpDir()!;\n this.pageClass = pageClass;\n this.agentClass = agentClass;\n this.staticPath = staticPath;\n this.taskProgressTips = {};\n this.activeAgents = {};\n setup();\n }\n\n filePathForUuid(uuid: string) {\n return join(this.tmpDir, `${uuid}.json`);\n }\n\n saveContextFile(uuid: string, context: string) {\n const tmpFile = this.filePathForUuid(uuid);\n console.log(`save context file: ${tmpFile}`);\n writeFileSync(tmpFile, context);\n return tmpFile;\n }\n\n async launch(port?: number) {\n this.port = port || defaultPort;\n this.app.use(errorHandler);\n\n this.app.use(\n cors({\n origin: '*',\n credentials: true,\n }),\n );\n\n this.app.get('/status', async (req: Request, res: Response) => {\n // const modelName = g\n res.send({\n status: 'ok',\n });\n });\n\n this.app.get('/context/:uuid', async (req: Request, res: Response) => {\n const { uuid } = req.params;\n const contextFile = this.filePathForUuid(uuid);\n\n if (!existsSync(contextFile)) {\n return res.status(404).json({\n error: 'Context not found',\n });\n }\n\n const context = readFileSync(contextFile, 'utf8');\n res.json({\n context,\n });\n });\n\n this.app.get(\n '/task-progress/:requestId',\n async (req: Request, res: Response) => {\n const { requestId } = req.params;\n res.json({\n tip: this.taskProgressTips[requestId] || '',\n });\n },\n );\n\n this.app.post(\n '/action-space',\n express.json({ limit: '30mb' }),\n async (req: Request, res: Response) => {\n const { context } = req.body;\n\n if (!context) {\n return res.status(400).json({\n error: 'context is required',\n });\n }\n\n try {\n // Create agent with context like in /execute\n const page = new this.pageClass(context);\n const actionSpace = await page.actionSpace();\n\n // Process actionSpace to make paramSchema serializable\n const processedActionSpace = actionSpace.map((action: any) => {\n if (action.paramSchema && typeof action.paramSchema === 'object') {\n // Extract shape information from Zod schema\n let processedSchema = null;\n\n try {\n // Extract shape from runtime Zod object\n if (\n action.paramSchema.shape &&\n typeof action.paramSchema.shape === 'object'\n ) {\n processedSchema = {\n type: 'ZodObject',\n shape: action.paramSchema.shape,\n };\n }\n } catch (e) {\n console.warn(\n 'Failed to process paramSchema for action:',\n action.name,\n e,\n );\n }\n\n return {\n ...action,\n paramSchema: processedSchema,\n };\n }\n return action;\n });\n\n res.json(processedActionSpace);\n } catch (error: any) {\n console.error('Failed to get action space:', error);\n res.status(500).json({\n error: error.message,\n });\n }\n },\n );\n\n // -------------------------\n // actions from report file\n this.app.post(\n '/playground-with-context',\n express.json({ limit: '50mb' }),\n async (req: Request, res: Response) => {\n const context = req.body.context;\n\n if (!context) {\n return res.status(400).json({\n error: 'context is required',\n });\n }\n\n const uuid = randomUUID();\n this.saveContextFile(uuid, context);\n return res.json({\n location: `/playground/${uuid}`,\n uuid,\n });\n },\n );\n\n this.app.post(\n '/execute',\n express.json({ limit: '30mb' }),\n async (req: Request, res: Response) => {\n const {\n context,\n type,\n prompt,\n params,\n requestId,\n deepThink,\n screenshotIncluded,\n domIncluded,\n } = req.body;\n\n if (!context) {\n return res.status(400).json({\n error: 'context is required',\n });\n }\n\n if (!type) {\n return res.status(400).json({\n error: 'type is required',\n });\n }\n\n // build an agent with context\n const page = new this.pageClass(context);\n const agent = new this.agentClass(page);\n\n if (requestId) {\n this.taskProgressTips[requestId] = '';\n this.activeAgents[requestId] = agent;\n\n agent.onTaskStartTip = (tip: string) => {\n this.taskProgressTips[requestId] = tip;\n };\n }\n\n const response: {\n result: any;\n dump: string | null;\n error: string | null;\n reportHTML: string | null;\n requestId?: string;\n } = {\n result: null,\n dump: null,\n error: null,\n reportHTML: null,\n requestId,\n };\n\n const startTime = Date.now();\n try {\n // Get action space to check for dynamic actions\n const actionSpace = await page.actionSpace();\n\n // Prepare value object for executeAction\n const value = {\n type,\n prompt,\n params,\n };\n\n response.result = await executeAction(\n agent as unknown as PlaygroundAgent,\n type,\n actionSpace,\n value,\n {\n deepThink: deepThink || false,\n screenshotIncluded,\n domIncluded,\n },\n );\n } catch (error: any) {\n response.error = formatErrorMessage(error);\n }\n\n try {\n response.dump = JSON.parse(agent.dumpDataString());\n response.reportHTML = agent.reportHTMLString() || null;\n\n agent.writeOutActionDumps();\n agent.destroy();\n } catch (error: any) {\n console.error(\n `write out dump failed: requestId: ${requestId}, ${error.message}`,\n );\n }\n\n res.send(response);\n const timeCost = Date.now() - startTime;\n\n if (response.error) {\n console.error(\n `handle request failed after ${timeCost}ms: requestId: ${requestId}, ${response.error}`,\n );\n } else {\n console.log(\n `handle request done after ${timeCost}ms: requestId: ${requestId}`,\n );\n }\n\n // Clean up the agent from activeAgents after execution completes\n if (requestId && this.activeAgents[requestId]) {\n delete this.activeAgents[requestId];\n }\n },\n );\n\n this.app.get('/cancel/:requestId', async (req: Request, res: Response) => {\n const { requestId } = req.params;\n\n if (!requestId) {\n return res.status(400).json({\n error: 'requestId is required',\n });\n }\n\n const agent = this.activeAgents[requestId];\n if (!agent) {\n return res.status(404).json({\n error: 'No active agent found for this requestId',\n });\n }\n\n try {\n await agent.destroy();\n delete this.activeAgents[requestId];\n res.json({ status: 'cancelled' });\n } catch (error: any) {\n console.error(`Failed to cancel agent: ${error.message}`);\n res.status(500).json({\n error: `Failed to cancel: ${error.message}`,\n });\n }\n });\n\n this.app.post(\n '/config',\n express.json({ limit: '1mb' }),\n async (req: Request, res: Response) => {\n const { aiConfig } = req.body;\n\n if (!aiConfig || typeof aiConfig !== 'object') {\n return res.status(400).json({\n error: 'aiConfig is required and must be an object',\n });\n }\n\n try {\n overrideAIConfig(aiConfig);\n\n return res.json({\n status: 'ok',\n message: 'AI config updated successfully',\n });\n } catch (error: any) {\n console.error(`Failed to update AI config: ${error.message}`);\n return res.status(500).json({\n error: `Failed to update AI config: ${error.message}`,\n });\n }\n },\n );\n\n // Set up static file serving after all API routes are defined\n if (this.staticPath) {\n this.app.get('/', (_req: Request, res: Response) => {\n // compatible with windows\n res.redirect('/index.html');\n });\n\n this.app.get('*', (req: Request, res: Response) => {\n const requestedPath = join(this.staticPath!, req.path);\n if (existsSync(requestedPath)) {\n res.sendFile(requestedPath);\n } else {\n res.sendFile(join(this.staticPath!, 'index.html'));\n }\n });\n }\n\n return new Promise((resolve) => {\n const port = this.port;\n this.server = this.app.listen(port, () => {\n resolve(this);\n });\n });\n }\n\n close() {\n // close the server\n if (this.server) {\n return this.server.close();\n }\n }\n}\n"],"names":["defaultPort","PLAYGROUND_SERVER_PORT","errorHandler","err","req","res","next","console","setup","ifInBrowser","ifInWorker","dotenv","PlaygroundServer","uuid","join","context","tmpFile","writeFileSync","port","cors","contextFile","existsSync","readFileSync","requestId","express","page","actionSpace","processedActionSpace","action","processedSchema","e","error","randomUUID","type","prompt","params","deepThink","screenshotIncluded","domIncluded","agent","tip","response","startTime","Date","value","executeAction","formatErrorMessage","JSON","timeCost","aiConfig","overrideAIConfig","_req","requestedPath","Promise","resolve","pageClass","agentClass","staticPath","getTmpDir"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.mjs","sources":["webpack://@midscene/playground/./src/server.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport type { Server } from 'node:http';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Agent as PageAgent } from '@midscene/core/agent';\nimport type { AbstractInterface } from '@midscene/core/device';\nimport { getTmpDir } from '@midscene/core/utils';\nimport { PLAYGROUND_SERVER_PORT } from '@midscene/shared/constants';\nimport { overrideAIConfig } from '@midscene/shared/env';\nimport express, { type Request, type Response } from 'express';\nimport { executeAction, formatErrorMessage } from './common';\nimport type { PlaygroundAgent } from './types';\n\nimport 'dotenv/config';\n\nconst defaultPort = PLAYGROUND_SERVER_PORT;\n\n// Static path for playground files\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst STATIC_PATH = join(__dirname, '..', '..', 'static');\n\nconst errorHandler = (\n err: unknown,\n req: Request,\n res: Response,\n next: express.NextFunction,\n) => {\n console.error(err);\n const errorMessage =\n err instanceof Error ? err.message : 'Internal server error';\n res.status(500).json({\n error: errorMessage,\n });\n};\n\nclass PlaygroundServer {\n private _app: express.Application;\n tmpDir: string;\n server?: Server;\n port?: number | null;\n page: AbstractInterface;\n agent: PageAgent;\n staticPath: string;\n taskProgressTips: Record<string, string>;\n\n private _initialized = false;\n\n constructor(\n page: AbstractInterface,\n agent: PageAgent,\n staticPath = STATIC_PATH,\n ) {\n this._app = express();\n this.tmpDir = getTmpDir()!;\n this.page = page;\n this.agent = agent;\n this.staticPath = staticPath;\n this.taskProgressTips = {};\n }\n\n /**\n * Get the Express app instance for custom configuration\n *\n * IMPORTANT: Add middleware (like CORS) BEFORE calling launch()\n * The routes are initialized when launch() is called, so middleware\n * added after launch() will not affect the API routes.\n *\n * @example\n * ```typescript\n * import cors from 'cors';\n *\n * const server = new PlaygroundServer(page, agent);\n *\n * // Add CORS middleware before launch\n * server.app.use(cors({\n * origin: true,\n * credentials: true,\n * methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']\n * }));\n *\n * await server.launch();\n * ```\n */\n get app(): express.Application {\n return this._app;\n }\n\n /**\n * Initialize Express app with all routes and middleware\n * Called automatically by launch() if not already initialized\n */\n private initializeApp(): void {\n if (this._initialized) return;\n\n // Built-in middleware to parse JSON bodies\n this._app.use(express.json({ limit: '50mb' }));\n\n // Context update middleware (after JSON parsing)\n this._app.use(\n (req: Request, _res: Response, next: express.NextFunction) => {\n const { context } = req.body || {};\n if (\n context &&\n 'updateContext' in this.page &&\n typeof this.page.updateContext === 'function'\n ) {\n this.page.updateContext(context);\n console.log('Context updated by PlaygroundServer middleware');\n }\n next();\n },\n );\n\n // NOTE: CORS middleware should be added externally via server.app.use()\n // before calling server.launch() if needed\n\n // API routes\n this.setupRoutes();\n\n // Static file serving (if staticPath is provided)\n this.setupStaticRoutes();\n\n // Error handler middleware (must be last)\n this._app.use(errorHandler);\n\n this._initialized = true;\n }\n\n filePathForUuid(uuid: string) {\n return join(this.tmpDir, `${uuid}.json`);\n }\n\n saveContextFile(uuid: string, context: string) {\n const tmpFile = this.filePathForUuid(uuid);\n console.log(`save context file: ${tmpFile}`);\n writeFileSync(tmpFile, context);\n return tmpFile;\n }\n\n /**\n * Setup all API routes\n */\n private setupRoutes(): void {\n this._app.get('/status', async (req: Request, res: Response) => {\n res.send({\n status: 'ok',\n });\n });\n\n this._app.get('/context/:uuid', async (req: Request, res: Response) => {\n const { uuid } = req.params;\n const contextFile = this.filePathForUuid(uuid);\n\n if (!existsSync(contextFile)) {\n return res.status(404).json({\n error: 'Context not found',\n });\n }\n\n const context = readFileSync(contextFile, 'utf8');\n res.json({\n context,\n });\n });\n\n this._app.get(\n '/task-progress/:requestId',\n async (req: Request, res: Response) => {\n const { requestId } = req.params;\n res.json({\n tip: this.taskProgressTips[requestId] || '',\n });\n },\n );\n\n this._app.post('/action-space', async (req: Request, res: Response) => {\n try {\n let actionSpace = [];\n\n actionSpace = await this.page.actionSpace();\n\n // Process actionSpace to make paramSchema serializable with shape info\n const processedActionSpace = actionSpace.map((action: unknown) => {\n if (action && typeof action === 'object' && 'paramSchema' in action) {\n const typedAction = action as {\n paramSchema?: { shape?: object; [key: string]: unknown };\n [key: string]: unknown;\n };\n if (\n typedAction.paramSchema &&\n typeof typedAction.paramSchema === 'object'\n ) {\n // Extract shape information from Zod schema\n let processedSchema = null;\n\n try {\n // Extract shape from runtime Zod object\n if (\n typedAction.paramSchema.shape &&\n typeof typedAction.paramSchema.shape === 'object'\n ) {\n processedSchema = {\n type: 'ZodObject',\n shape: typedAction.paramSchema.shape,\n };\n }\n } catch (e) {\n const actionName =\n 'name' in typedAction && typeof typedAction.name === 'string'\n ? typedAction.name\n : 'unknown';\n console.warn(\n 'Failed to process paramSchema for action:',\n actionName,\n e,\n );\n }\n\n return {\n ...typedAction,\n paramSchema: processedSchema,\n };\n }\n }\n return action;\n });\n\n res.json(processedActionSpace);\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error('Failed to get action space:', error);\n res.status(500).json({\n error: errorMessage,\n });\n }\n });\n\n // -------------------------\n // actions from report file\n this._app.post(\n '/playground-with-context',\n async (req: Request, res: Response) => {\n const context = req.body.context;\n\n if (!context) {\n return res.status(400).json({\n error: 'context is required',\n });\n }\n\n const uuid = randomUUID();\n this.saveContextFile(uuid, context);\n return res.json({\n location: `/playground/${uuid}`,\n uuid,\n });\n },\n );\n\n this._app.post('/execute', async (req: Request, res: Response) => {\n const {\n type,\n prompt,\n params,\n requestId,\n deepThink,\n screenshotIncluded,\n domIncluded,\n } = req.body;\n\n if (!type) {\n return res.status(400).json({\n error: 'type is required',\n });\n }\n\n if (requestId) {\n this.taskProgressTips[requestId] = '';\n\n this.agent.onTaskStartTip = (tip: string) => {\n this.taskProgressTips[requestId] = tip;\n };\n }\n\n const response: {\n result: unknown;\n dump: string | null;\n error: string | null;\n reportHTML: string | null;\n requestId?: string;\n } = {\n result: null,\n dump: null,\n error: null,\n reportHTML: null,\n requestId,\n };\n\n const startTime = Date.now();\n try {\n // Get action space to check for dynamic actions\n const actionSpace = await this.page.actionSpace();\n\n // Prepare value object for executeAction\n const value = {\n type,\n prompt,\n params,\n };\n\n response.result = await executeAction(\n this.agent,\n type,\n actionSpace,\n value,\n {\n deepThink: deepThink || false,\n screenshotIncluded,\n domIncluded,\n },\n );\n } catch (error: unknown) {\n response.error = formatErrorMessage(error);\n }\n\n try {\n response.dump = JSON.parse(this.agent.dumpDataString());\n response.reportHTML = this.agent.reportHTMLString() || null;\n\n this.agent.writeOutActionDumps();\n this.agent.resetDump();\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(\n `write out dump failed: requestId: ${requestId}, ${errorMessage}`,\n );\n }\n\n res.send(response);\n const timeCost = Date.now() - startTime;\n\n if (response.error) {\n console.error(\n `handle request failed after ${timeCost}ms: requestId: ${requestId}, ${response.error}`,\n );\n } else {\n console.log(\n `handle request done after ${timeCost}ms: requestId: ${requestId}`,\n );\n }\n\n // Clean up task progress tip after execution completes\n if (requestId) {\n delete this.taskProgressTips[requestId];\n }\n });\n\n this._app.post(\n '/cancel/:requestId',\n async (req: Request, res: Response) => {\n const { requestId } = req.params;\n\n if (!requestId) {\n return res.status(400).json({\n error: 'requestId is required',\n });\n }\n\n try {\n // Since we only have one agent, just clear the task progress tip\n if (this.taskProgressTips[requestId]) {\n delete this.taskProgressTips[requestId];\n }\n res.json({ status: 'cancelled' });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to cancel: ${errorMessage}`);\n res.status(500).json({\n error: `Failed to cancel: ${errorMessage}`,\n });\n }\n },\n );\n\n // Screenshot API for real-time screenshot polling\n this._app.get('/screenshot', async (_req: Request, res: Response) => {\n try {\n // Check if page has screenshotBase64 method\n if (typeof this.page.screenshotBase64 !== 'function') {\n return res.status(500).json({\n error: 'Screenshot method not available on current interface',\n });\n }\n\n const base64Screenshot = await this.page.screenshotBase64();\n\n res.json({\n screenshot: base64Screenshot,\n timestamp: Date.now(),\n });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to take screenshot: ${errorMessage}`);\n res.status(500).json({\n error: `Failed to take screenshot: ${errorMessage}`,\n });\n }\n });\n\n this.app.post('/config', async (req: Request, res: Response) => {\n const { aiConfig } = req.body;\n\n if (!aiConfig || typeof aiConfig !== 'object') {\n return res.status(400).json({\n error: 'aiConfig is required and must be an object',\n });\n }\n\n try {\n overrideAIConfig(aiConfig);\n\n return res.json({\n status: 'ok',\n message: 'AI config updated successfully',\n });\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to update AI config: ${errorMessage}`);\n return res.status(500).json({\n error: `Failed to update AI config: ${errorMessage}`,\n });\n }\n });\n }\n\n /**\n * Setup static file serving routes\n */\n private setupStaticRoutes(): void {\n this._app.get('/', (_req: Request, res: Response) => {\n // compatible with windows\n res.redirect('/index.html');\n });\n\n // Use express.static middleware for secure static file serving\n this._app.use(express.static(this.staticPath));\n\n // Fallback to index.html for SPA routing\n this._app.get('*', (_req: Request, res: Response) => {\n res.sendFile(join(this.staticPath, 'index.html'));\n });\n }\n\n /**\n * Launch the server on specified port\n */\n async launch(port?: number): Promise<PlaygroundServer> {\n // Initialize routes now, after any middleware has been added\n this.initializeApp();\n\n this.port = port || defaultPort;\n\n return new Promise((resolve) => {\n const serverPort = this.port;\n this.server = this._app.listen(serverPort, () => {\n resolve(this);\n });\n });\n }\n\n /**\n * Close the server and clean up resources\n */\n async close(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.server) {\n // Clean up the single agent\n try {\n this.agent.destroy();\n } catch (error) {\n console.warn('Failed to destroy agent:', error);\n }\n this.taskProgressTips = {};\n\n // Close the server\n this.server.close((error) => {\n if (error) {\n reject(error);\n } else {\n this.server = undefined;\n resolve();\n }\n });\n } else {\n resolve();\n }\n });\n }\n}\n\nexport default PlaygroundServer;\nexport { PlaygroundServer };\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","contextFile","existsSync","readFileSync","requestId","actionSpace","processedActionSpace","action","typedAction","processedSchema","e","actionName","error","randomUUID","type","prompt","params","deepThink","screenshotIncluded","domIncluded","tip","response","startTime","Date","value","executeAction","formatErrorMessage","JSON","timeCost","_req","base64Screenshot","aiConfig","overrideAIConfig","port","Promise","resolve","serverPort","reject","undefined","page","agent","staticPath","getTmpDir"],"mappings":"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"}
|
|
@@ -41,6 +41,9 @@ function _define_property(obj, key, value) {
|
|
|
41
41
|
return obj;
|
|
42
42
|
}
|
|
43
43
|
class LocalExecutionAdapter extends external_base_js_namespaceObject.BasePlaygroundAdapter {
|
|
44
|
+
setProgressCallback(callback) {
|
|
45
|
+
this.progressCallback = callback;
|
|
46
|
+
}
|
|
44
47
|
cleanup(requestId) {
|
|
45
48
|
delete this.taskProgressTips[requestId];
|
|
46
49
|
}
|
|
@@ -67,8 +70,18 @@ class LocalExecutionAdapter extends external_base_js_namespaceObject.BasePlaygro
|
|
|
67
70
|
if (errorMessage.includes('of different extension')) return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';
|
|
68
71
|
return this.formatBasicErrorMessage(error);
|
|
69
72
|
}
|
|
70
|
-
async getActionSpace(
|
|
71
|
-
|
|
73
|
+
async getActionSpace(context) {
|
|
74
|
+
var _this_agent;
|
|
75
|
+
if (null == (_this_agent = this.agent) ? void 0 : _this_agent.getActionSpace) return await this.agent.getActionSpace();
|
|
76
|
+
if (this.agent && 'interface' in this.agent && 'object' == typeof this.agent.interface) {
|
|
77
|
+
const page = this.agent.interface;
|
|
78
|
+
if (null == page ? void 0 : page.actionSpace) return await page.actionSpace();
|
|
79
|
+
}
|
|
80
|
+
if (context && 'object' == typeof context && 'actionSpace' in context) {
|
|
81
|
+
const contextPage = context;
|
|
82
|
+
return await contextPage.actionSpace();
|
|
83
|
+
}
|
|
84
|
+
return [];
|
|
72
85
|
}
|
|
73
86
|
async checkStatus() {
|
|
74
87
|
return true;
|
|
@@ -77,16 +90,35 @@ class LocalExecutionAdapter extends external_base_js_namespaceObject.BasePlaygro
|
|
|
77
90
|
(0, env_namespaceObject.overrideAIConfig)(aiConfig);
|
|
78
91
|
}
|
|
79
92
|
async executeAction(actionType, value, options) {
|
|
80
|
-
const actionSpace =
|
|
93
|
+
const actionSpace = await this.getActionSpace();
|
|
81
94
|
if (options.requestId && this.agent) {
|
|
82
95
|
const originalCallback = this.agent.onTaskStartTip;
|
|
83
96
|
this.agent.onTaskStartTip = (tip)=>{
|
|
84
97
|
this.taskProgressTips[options.requestId] = tip;
|
|
98
|
+
if (this.progressCallback) this.progressCallback(tip);
|
|
85
99
|
if (originalCallback && 'function' == typeof originalCallback) originalCallback(tip);
|
|
86
100
|
};
|
|
87
101
|
}
|
|
88
102
|
try {
|
|
89
|
-
|
|
103
|
+
const result = await (0, external_common_js_namespaceObject.executeAction)(this.agent, actionType, actionSpace, value, options);
|
|
104
|
+
const response = {
|
|
105
|
+
result,
|
|
106
|
+
dump: null,
|
|
107
|
+
reportHTML: null,
|
|
108
|
+
error: null
|
|
109
|
+
};
|
|
110
|
+
try {
|
|
111
|
+
if (this.agent.dumpDataString) {
|
|
112
|
+
const dumpString = this.agent.dumpDataString();
|
|
113
|
+
if (dumpString) response.dump = JSON.parse(dumpString);
|
|
114
|
+
}
|
|
115
|
+
if (this.agent.reportHTMLString) response.reportHTML = this.agent.reportHTMLString() || null;
|
|
116
|
+
if (this.agent.writeOutActionDumps) this.agent.writeOutActionDumps();
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error('Failed to get dump/reportHTML from agent:', error);
|
|
119
|
+
}
|
|
120
|
+
this.agent.resetDump();
|
|
121
|
+
return response;
|
|
90
122
|
} finally{
|
|
91
123
|
if (options.requestId) this.cleanup(options.requestId);
|
|
92
124
|
}
|
|
@@ -107,14 +139,15 @@ class LocalExecutionAdapter extends external_base_js_namespaceObject.BasePlaygro
|
|
|
107
139
|
success: true
|
|
108
140
|
};
|
|
109
141
|
} catch (error) {
|
|
110
|
-
|
|
142
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
143
|
+
console.error(`Failed to cancel agent: ${errorMessage}`);
|
|
111
144
|
return {
|
|
112
|
-
error: `Failed to cancel: ${
|
|
145
|
+
error: `Failed to cancel: ${errorMessage}`
|
|
113
146
|
};
|
|
114
147
|
}
|
|
115
148
|
}
|
|
116
149
|
constructor(agent){
|
|
117
|
-
super(), _define_property(this, "agent", void 0), _define_property(this, "taskProgressTips", {});
|
|
150
|
+
super(), _define_property(this, "agent", void 0), _define_property(this, "taskProgressTips", {}), _define_property(this, "progressCallback", void 0);
|
|
118
151
|
this.agent = agent;
|
|
119
152
|
}
|
|
120
153
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters/local-execution.js","sources":["webpack://@midscene/playground/webpack/runtime/define_property_getters","webpack://@midscene/playground/webpack/runtime/has_own_property","webpack://@midscene/playground/webpack/runtime/make_namespace_object","webpack://@midscene/playground/./src/adapters/local-execution.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { DeviceAction } from '@midscene/core';\nimport { findAllMidsceneLocatorField } from '@midscene/core/ai-model';\nimport { overrideAIConfig } from '@midscene/shared/env';\nimport { executeAction } from '../common';\nimport type { ExecutionOptions, FormValue, PlaygroundAgent } from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class LocalExecutionAdapter extends BasePlaygroundAdapter {\n private agent: PlaygroundAgent;\n private taskProgressTips: Record<string, string> = {};\n\n constructor(agent: PlaygroundAgent) {\n super();\n this.agent = agent;\n }\n\n private cleanup(requestId: string): void {\n delete this.taskProgressTips[requestId];\n }\n\n async parseStructuredParams(\n action: DeviceAction<unknown>,\n params: Record<string, unknown>,\n options: ExecutionOptions,\n ): Promise<unknown[]> {\n if (!action?.paramSchema || !('shape' in action.paramSchema)) {\n return [params.prompt || '', options];\n }\n\n const locatorFieldKeys = findAllMidsceneLocatorField(action.paramSchema);\n\n // Find locate field (MidsceneLocation field)\n let locateField = null;\n if (locatorFieldKeys.length > 0) {\n locateField = params[locatorFieldKeys[0]];\n }\n\n // Filter non-locate fields\n const nonLocateFields = this.filterValidParams(params, locatorFieldKeys);\n\n // Local execution format: [locateField, { ...otherParams, ...options }]\n const paramObj = { ...nonLocateFields, ...options };\n return [locateField, paramObj];\n }\n\n formatErrorMessage(error: any): string {\n const errorMessage = error?.message || '';\n if (errorMessage.includes('of different extension')) {\n return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';\n }\n return this.formatBasicErrorMessage(error);\n }\n\n // Local execution - use base implementation\n // (inherits default executeAction from BasePlaygroundAdapter)\n\n // Local execution gets actionSpace directly from local agent\n async getActionSpace(page: any): Promise<DeviceAction<unknown>[]> {\n return await page.actionSpace();\n }\n\n // Local execution doesn't use a server, so always return true\n async checkStatus(): Promise<boolean> {\n return true;\n }\n\n async overrideConfig(aiConfig: any): Promise<void> {\n // For local execution, use the shared env override function\n overrideAIConfig(aiConfig);\n }\n\n async executeAction(\n actionType: string,\n value: FormValue,\n options: ExecutionOptions,\n ): Promise<unknown> {\n // Get actionSpace from the stored agent\n const actionSpace = this.agent.getActionSpace\n ? await this.agent.getActionSpace()\n : [];\n\n // Setup progress tracking if requestId is provided\n if (options.requestId && this.agent) {\n // Store the original callback if exists\n const originalCallback = this.agent.onTaskStartTip;\n\n // Override with our callback that stores tips and calls original\n this.agent.onTaskStartTip = (tip: string) => {\n // Store tip for our progress tracking\n this.taskProgressTips[options.requestId!] = tip;\n // Call original callback if it existed\n if (originalCallback && typeof originalCallback === 'function') {\n originalCallback(tip);\n }\n };\n }\n\n try {\n // Call the base implementation with the original signature\n return await executeAction(\n this.agent,\n actionType,\n actionSpace,\n value,\n options,\n );\n } finally {\n // Always clean up progress tracking to prevent memory leaks\n if (options.requestId) {\n this.cleanup(options.requestId);\n }\n }\n }\n\n async getTaskProgress(requestId: string): Promise<{ tip?: string }> {\n // Return the stored tip for this requestId\n return { tip: this.taskProgressTips[requestId] || undefined };\n }\n\n // Local execution task cancellation - minimal implementation\n async cancelTask(\n _requestId: string,\n ): Promise<{ error?: string; success?: boolean }> {\n if (!this.agent) {\n return { error: 'No active agent found for this requestId' };\n }\n\n try {\n await this.agent.destroy?.();\n return { success: true };\n } catch (error: any) {\n console.error(`Failed to cancel agent: ${error.message}`);\n return { error: `Failed to cancel: ${error.message}` };\n }\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","LocalExecutionAdapter","BasePlaygroundAdapter","requestId","action","params","options","locatorFieldKeys","findAllMidsceneLocatorField","locateField","nonLocateFields","paramObj","error","errorMessage","page","aiConfig","overrideAIConfig","actionType","value","actionSpace","originalCallback","tip","executeAction","undefined","_requestId","_this_agent","console","agent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapters/local-execution.js","sources":["webpack://@midscene/playground/webpack/runtime/define_property_getters","webpack://@midscene/playground/webpack/runtime/has_own_property","webpack://@midscene/playground/webpack/runtime/make_namespace_object","webpack://@midscene/playground/./src/adapters/local-execution.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { DeviceAction } from '@midscene/core';\nimport { findAllMidsceneLocatorField } from '@midscene/core/ai-model';\nimport { overrideAIConfig } from '@midscene/shared/env';\nimport { executeAction } from '../common';\nimport type { ExecutionOptions, FormValue, PlaygroundAgent } from '../types';\nimport { BasePlaygroundAdapter } from './base';\n\nexport class LocalExecutionAdapter extends BasePlaygroundAdapter {\n private agent: PlaygroundAgent;\n private taskProgressTips: Record<string, string> = {};\n private progressCallback?: (tip: string) => void;\n\n constructor(agent: PlaygroundAgent) {\n super();\n this.agent = agent;\n }\n\n setProgressCallback(callback: (tip: string) => void): void {\n this.progressCallback = callback;\n }\n\n private cleanup(requestId: string): void {\n delete this.taskProgressTips[requestId];\n }\n\n async parseStructuredParams(\n action: DeviceAction<unknown>,\n params: Record<string, unknown>,\n options: ExecutionOptions,\n ): Promise<unknown[]> {\n if (!action?.paramSchema || !('shape' in action.paramSchema)) {\n return [params.prompt || '', options];\n }\n\n const locatorFieldKeys = findAllMidsceneLocatorField(action.paramSchema);\n\n // Find locate field (MidsceneLocation field)\n let locateField = null;\n if (locatorFieldKeys.length > 0) {\n locateField = params[locatorFieldKeys[0]];\n }\n\n // Filter non-locate fields\n const nonLocateFields = this.filterValidParams(params, locatorFieldKeys);\n\n // Local execution format: [locateField, { ...otherParams, ...options }]\n const paramObj = { ...nonLocateFields, ...options };\n return [locateField, paramObj];\n }\n\n formatErrorMessage(error: any): string {\n const errorMessage = error?.message || '';\n if (errorMessage.includes('of different extension')) {\n return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';\n }\n return this.formatBasicErrorMessage(error);\n }\n\n // Local execution - use base implementation\n // (inherits default executeAction from BasePlaygroundAdapter)\n\n // Local execution gets actionSpace from internal agent (parameter is for backward compatibility)\n async getActionSpace(context?: unknown): Promise<DeviceAction<unknown>[]> {\n // Priority 1: Use agent's getActionSpace method\n if (this.agent?.getActionSpace) {\n return await this.agent.getActionSpace();\n }\n\n // Priority 2: Use agent's interface.actionSpace method\n if (\n this.agent &&\n 'interface' in this.agent &&\n typeof this.agent.interface === 'object'\n ) {\n const page = this.agent.interface as {\n actionSpace?: () => Promise<DeviceAction<unknown>[]>;\n };\n if (page?.actionSpace) {\n return await page.actionSpace();\n }\n }\n\n // Priority 3: Fallback to context parameter (for backward compatibility with tests)\n if (context && typeof context === 'object' && 'actionSpace' in context) {\n const contextPage = context as {\n actionSpace: () => Promise<DeviceAction<unknown>[]>;\n };\n return await contextPage.actionSpace();\n }\n\n return [];\n }\n\n // Local execution doesn't use a server, so always return true\n async checkStatus(): Promise<boolean> {\n return true;\n }\n\n async overrideConfig(aiConfig: Record<string, unknown>): Promise<void> {\n // For local execution, use the shared env override function\n overrideAIConfig(aiConfig);\n }\n\n async executeAction(\n actionType: string,\n value: FormValue,\n options: ExecutionOptions,\n ): Promise<unknown> {\n // Get actionSpace using our simplified getActionSpace method\n const actionSpace = await this.getActionSpace();\n\n // Setup progress tracking if requestId is provided\n if (options.requestId && this.agent) {\n // Store the original callback if exists (this preserves chrome extension callbacks)\n const originalCallback = this.agent.onTaskStartTip;\n\n // Override with our callback that stores tips and calls original\n this.agent.onTaskStartTip = (tip: string) => {\n // Store tip for our progress tracking\n this.taskProgressTips[options.requestId!] = tip;\n\n // Call the direct progress callback set via setProgressCallback\n if (this.progressCallback) {\n this.progressCallback(tip);\n }\n\n // Call original callback if it existed (this will call chrome extension callbacks)\n if (originalCallback && typeof originalCallback === 'function') {\n originalCallback(tip);\n }\n };\n }\n\n try {\n // Call the base implementation with the original signature\n const result = await executeAction(\n this.agent,\n actionType,\n actionSpace,\n value,\n options,\n );\n\n // For local execution, we need to package the result with dump and reportHTML\n // similar to how the server does it\n const response = {\n result,\n dump: null as unknown,\n reportHTML: null as string | null,\n error: null as string | null,\n };\n\n try {\n // Get dump and reportHTML from agent like the server does\n if (this.agent.dumpDataString) {\n const dumpString = this.agent.dumpDataString();\n if (dumpString) {\n response.dump = JSON.parse(dumpString);\n }\n }\n\n if (this.agent.reportHTMLString) {\n response.reportHTML = this.agent.reportHTMLString() || null;\n }\n\n // Write out action dumps\n if (this.agent.writeOutActionDumps) {\n this.agent.writeOutActionDumps();\n }\n } catch (error: unknown) {\n console.error('Failed to get dump/reportHTML from agent:', error);\n }\n\n this.agent.resetDump();\n\n return response;\n } finally {\n // Always clean up progress tracking to prevent memory leaks\n if (options.requestId) {\n this.cleanup(options.requestId);\n }\n }\n }\n\n async getTaskProgress(requestId: string): Promise<{ tip?: string }> {\n // Return the stored tip for this requestId\n return { tip: this.taskProgressTips[requestId] || undefined };\n }\n\n // Local execution task cancellation - minimal implementation\n async cancelTask(\n _requestId: string,\n ): Promise<{ error?: string; success?: boolean }> {\n if (!this.agent) {\n return { error: 'No active agent found for this requestId' };\n }\n\n try {\n await this.agent.destroy?.();\n return { success: true };\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n console.error(`Failed to cancel agent: ${errorMessage}`);\n return { error: `Failed to cancel: ${errorMessage}` };\n }\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","LocalExecutionAdapter","BasePlaygroundAdapter","callback","requestId","action","params","options","locatorFieldKeys","findAllMidsceneLocatorField","locateField","nonLocateFields","paramObj","error","errorMessage","context","_this_agent","page","contextPage","aiConfig","overrideAIConfig","actionType","value","actionSpace","originalCallback","tip","result","executeAction","response","dumpString","JSON","console","undefined","_requestId","Error","agent"],"mappings":"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"}
|