@midscene/test 1.12.4-beta-20260903111111.0 → 1.12.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/android/index.mjs +50 -106
- package/dist/es/android/index.mjs.map +1 -1
- package/dist/es/cli/index.mjs +99 -149
- package/dist/es/cli/index.mjs.map +1 -1
- package/dist/es/harmony/index.mjs +119 -0
- package/dist/es/harmony/index.mjs.map +1 -0
- package/dist/es/index.mjs +36 -87
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/ios/index.mjs +51 -101
- package/dist/es/ios/index.mjs.map +1 -1
- package/dist/es/midscene/index.mjs +37 -235
- package/dist/es/midscene/index.mjs.map +1 -1
- package/dist/es/playwright/index.mjs +14 -10
- package/dist/es/playwright/index.mjs.map +1 -1
- package/dist/es/test-cli.mjs +102 -150
- package/dist/es/test-cli.mjs.map +1 -1
- package/dist/lib/android/index.js +151 -178
- package/dist/lib/android/index.js.map +1 -1
- package/dist/lib/cli/index.js +99 -149
- package/dist/lib/cli/index.js.map +1 -1
- package/dist/lib/harmony/index.js +188 -0
- package/dist/lib/harmony/index.js.map +1 -0
- package/dist/lib/index.js +37 -100
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/ios/index.js +152 -173
- package/dist/lib/ios/index.js.map +1 -1
- package/dist/lib/midscene/index.js +264 -412
- package/dist/lib/midscene/index.js.map +1 -1
- package/dist/lib/playwright/index.js +14 -10
- package/dist/lib/playwright/index.js.map +1 -1
- package/dist/lib/test-cli.js +102 -150
- package/dist/lib/test-cli.js.map +1 -1
- package/dist/types/android/index.d.ts +27 -101
- package/dist/types/cli/index.d.ts +9 -32
- package/dist/types/harmony/index.d.ts +124 -0
- package/dist/types/index.d.ts +18 -45
- package/dist/types/ios/index.d.ts +28 -107
- package/dist/types/midscene/index.d.ts +54 -153
- package/dist/types/playwright/index.d.ts +9 -63
- package/package.json +25 -6
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
2
|
+
var __webpack_modules__ = {
|
|
3
|
+
"./src/errors.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
4
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
5
|
+
h2: ()=>NodeExecutionError,
|
|
6
|
+
ww: ()=>NodeDefinitionError
|
|
7
|
+
});
|
|
8
|
+
function _define_property(obj, key, value) {
|
|
9
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
10
|
+
value: value,
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true
|
|
14
|
+
});
|
|
15
|
+
else obj[key] = value;
|
|
16
|
+
return obj;
|
|
17
|
+
}
|
|
18
|
+
class WorkflowError extends Error {
|
|
19
|
+
toJSON() {
|
|
20
|
+
return {
|
|
21
|
+
name: this.name,
|
|
22
|
+
message: this.message,
|
|
23
|
+
code: this.code,
|
|
24
|
+
...void 0 === this.details ? {} : {
|
|
25
|
+
details: this.details
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
constructor(message, options = {}){
|
|
30
|
+
super(message, {
|
|
31
|
+
cause: options.cause
|
|
32
|
+
}), _define_property(this, "code", void 0), _define_property(this, "details", void 0);
|
|
33
|
+
this.name = new.target.name;
|
|
34
|
+
this.code = options.code ?? 'WORKFLOW_ERROR';
|
|
35
|
+
this.details = options.details;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
class NodeDefinitionError extends WorkflowError {
|
|
39
|
+
constructor(message, details){
|
|
40
|
+
super(message, {
|
|
41
|
+
code: 'NODE_DEFINITION_ERROR',
|
|
42
|
+
details
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
class NodeExecutionError extends WorkflowError {
|
|
47
|
+
constructor(node, cause){
|
|
48
|
+
const causeMessage = cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');
|
|
49
|
+
super(`Node "${node}" failed: ${causeMessage}`, {
|
|
50
|
+
code: 'NODE_EXECUTION_ERROR',
|
|
51
|
+
details: {
|
|
52
|
+
node
|
|
53
|
+
},
|
|
54
|
+
cause
|
|
55
|
+
}), _define_property(this, "node", void 0);
|
|
56
|
+
this.node = node;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var __webpack_module_cache__ = {};
|
|
62
|
+
function __webpack_require__(moduleId) {
|
|
63
|
+
var cachedModule = __webpack_module_cache__[moduleId];
|
|
64
|
+
if (void 0 !== cachedModule) return cachedModule.exports;
|
|
65
|
+
var module = __webpack_module_cache__[moduleId] = {
|
|
66
|
+
exports: {}
|
|
67
|
+
};
|
|
68
|
+
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
69
|
+
return module.exports;
|
|
70
|
+
}
|
|
3
71
|
(()=>{
|
|
4
72
|
__webpack_require__.d = (exports1, definition)=>{
|
|
5
73
|
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
@@ -22,440 +90,224 @@ var __webpack_require__ = {};
|
|
|
22
90
|
};
|
|
23
91
|
})();
|
|
24
92
|
var __webpack_exports__ = {};
|
|
25
|
-
|
|
26
|
-
__webpack_require__.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
class WorkflowError extends Error {
|
|
48
|
-
toJSON() {
|
|
49
|
-
return {
|
|
50
|
-
name: this.name,
|
|
51
|
-
message: this.message,
|
|
52
|
-
code: this.code,
|
|
53
|
-
...void 0 === this.details ? {} : {
|
|
54
|
-
details: this.details
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
constructor(message, options = {}){
|
|
59
|
-
super(message, {
|
|
60
|
-
cause: options.cause
|
|
61
|
-
}), _define_property(this, "code", void 0), _define_property(this, "details", void 0);
|
|
62
|
-
this.name = new.target.name;
|
|
63
|
-
this.code = options.code ?? 'WORKFLOW_ERROR';
|
|
64
|
-
this.details = options.details;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
class NodeDefinitionError extends WorkflowError {
|
|
68
|
-
constructor(message, details){
|
|
69
|
-
super(message, {
|
|
70
|
-
code: 'NODE_DEFINITION_ERROR',
|
|
71
|
-
details
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
class NodeExecutionError extends WorkflowError {
|
|
76
|
-
constructor(node, cause){
|
|
77
|
-
const causeMessage = cause instanceof Error ? cause.message : String(cause ?? 'Unknown error');
|
|
78
|
-
super(`Node "${node}" failed: ${causeMessage}`, {
|
|
79
|
-
code: 'NODE_EXECUTION_ERROR',
|
|
80
|
-
details: {
|
|
81
|
-
node
|
|
82
|
-
},
|
|
83
|
-
cause
|
|
84
|
-
}), _define_property(this, "node", void 0);
|
|
85
|
-
this.node = node;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const validateOptionalText = (value, field, node)=>{
|
|
89
|
-
if (void 0 !== value && ('string' != typeof value || 0 === value.trim().length)) throw new NodeDefinitionError(`Node "${node}" ${field} must be a non-empty string.`, {
|
|
90
|
-
node,
|
|
91
|
-
field
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
const validateInputSchema = (schema, node)=>{
|
|
95
|
-
if (void 0 === schema) return;
|
|
96
|
-
if (!(schema instanceof v4_namespaceObject.z.ZodObject)) throw new NodeDefinitionError(`Node "${node}" inputSchema must be a Zod object schema.`, {
|
|
97
|
-
node,
|
|
98
|
-
field: 'inputSchema'
|
|
99
|
-
});
|
|
100
|
-
if ('$' in schema.shape) throw new NodeDefinitionError(`Node "${node}" inputSchema must not declare "$" as an input property.`, {
|
|
101
|
-
node,
|
|
102
|
-
field: 'inputSchema.$'
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
const validateDefinition = (options)=>{
|
|
106
|
-
if (!options || 'object' != typeof options) throw new NodeDefinitionError('Node definition must be an object.');
|
|
107
|
-
if ('string' != typeof options.name || 0 === options.name.trim().length) throw new NodeDefinitionError('Node name must be a non-empty string.');
|
|
108
|
-
validateOptionalText(options.title, 'title', options.name);
|
|
109
|
-
validateOptionalText(options.description, "description", options.name);
|
|
110
|
-
validateInputSchema(options.inputSchema, options.name);
|
|
111
|
-
if ('function' != typeof options.execute) throw new NodeDefinitionError(`Node "${options.name}" must provide an execute function.`, {
|
|
112
|
-
node: options.name
|
|
93
|
+
(()=>{
|
|
94
|
+
__webpack_require__.r(__webpack_exports__);
|
|
95
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
96
|
+
createAgentTestRunnerNodes: ()=>createAgentTestRunnerNodes,
|
|
97
|
+
aiActOptionsInputSchema: ()=>test_runner_namespaceObject.aiActOptionsInputSchema,
|
|
98
|
+
aiTapInputSchema: ()=>test_runner_namespaceObject.aiTapInputSchema,
|
|
99
|
+
reportScreenshotInputSchema: ()=>test_runner_namespaceObject.reportScreenshotInputSchema,
|
|
100
|
+
insightInputSchema: ()=>test_runner_namespaceObject.insightInputSchema,
|
|
101
|
+
locateOptionsInputSchema: ()=>test_runner_namespaceObject.locateOptionsInputSchema,
|
|
102
|
+
structuredUserPromptInputSchema: ()=>test_runner_namespaceObject.structuredUserPromptInputSchema,
|
|
103
|
+
waitInputSchema: ()=>waitInputSchema,
|
|
104
|
+
promptImageInputSchema: ()=>test_runner_namespaceObject.promptImageInputSchema,
|
|
105
|
+
aiAssertInputSchema: ()=>test_runner_namespaceObject.aiAssertInputSchema,
|
|
106
|
+
createMidsceneNodes: ()=>createMidsceneNodes,
|
|
107
|
+
recordToReportInputSchema: ()=>test_runner_namespaceObject.recordToReportInputSchema,
|
|
108
|
+
recordToReportOptionsInputSchema: ()=>test_runner_namespaceObject.recordToReportOptionsInputSchema,
|
|
109
|
+
agentInputSchema: ()=>agentInputSchema,
|
|
110
|
+
userPromptInputSchema: ()=>test_runner_namespaceObject.userPromptInputSchema,
|
|
111
|
+
aiAssertOptionsInputSchema: ()=>test_runner_namespaceObject.aiAssertOptionsInputSchema,
|
|
112
|
+
aiActInputSchema: ()=>test_runner_namespaceObject.aiActInputSchema,
|
|
113
|
+
insightOptionsInputSchema: ()=>test_runner_namespaceObject.insightOptionsInputSchema
|
|
113
114
|
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
uri: v4_namespaceObject.z.string().regex(/\S/, 'uri must contain a non-whitespace character').optional().describe(description)
|
|
122
|
-
}).superRefine((input, ctx)=>{
|
|
123
|
-
if (void 0 === input.prompt === (void 0 === input.uri)) ctx.addIssue({
|
|
124
|
-
code: 'custom',
|
|
125
|
-
message: 'exactly one of prompt and uri is required'
|
|
115
|
+
const test_runner_namespaceObject = require("@midscene/core/agent/test-runner");
|
|
116
|
+
const v4_namespaceObject = require("zod/v4");
|
|
117
|
+
var errors = __webpack_require__("./src/errors.ts");
|
|
118
|
+
const validateOptionalText = (value, field, node)=>{
|
|
119
|
+
if (void 0 !== value && ('string' != typeof value || 0 === value.trim().length)) throw new errors.ww(`Node "${node}" ${field} must be a non-empty string.`, {
|
|
120
|
+
node,
|
|
121
|
+
field
|
|
126
122
|
});
|
|
127
|
-
});
|
|
128
|
-
const launchInputSchema = lifecycleInputSchema('launch', 'The app, URL, URI, package name, or bundle identifier to launch.');
|
|
129
|
-
lifecycleInputSchema('terminate', 'The package name, bundle identifier, or app name to terminate.');
|
|
130
|
-
const requireLifecycleMethod = (agent, method, agentName)=>{
|
|
131
|
-
if ('object' != typeof agent || null === agent || 'function' != typeof agent[method]) throw new NodeExecutionError(method, new TypeError(`getAgent() must return ${agentName} with ${method}().`));
|
|
132
|
-
return agent[method];
|
|
133
|
-
};
|
|
134
|
-
const createLaunchNode = (getAgent, agentName = 'an Agent')=>define_node_defineNode({
|
|
135
|
-
name: 'launch',
|
|
136
|
-
description: 'Launch an app, URL, or URI through the current Midscene Agent. This Node does not install or manage applications.',
|
|
137
|
-
inputSchema: launchInputSchema,
|
|
138
|
-
async execute (ctx) {
|
|
139
|
-
const uri = ctx.input.uri ?? ctx.input.prompt;
|
|
140
|
-
const agent = await getAgent(ctx);
|
|
141
|
-
const launch = requireLifecycleMethod(agent, 'launch', agentName);
|
|
142
|
-
await launch.call(agent, uri);
|
|
143
|
-
return {
|
|
144
|
-
summary: `Launched ${uri}`
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
const nonBlankPrompt = (description)=>v4_namespaceObject.z.string().regex(/\S/, 'prompt must contain a non-whitespace character').describe(description);
|
|
149
|
-
const promptImagesInputSchema = v4_namespaceObject.z.array(v4_namespaceObject.z.strictObject({
|
|
150
|
-
name: nonBlankPrompt('The name used to identify this reference image.'),
|
|
151
|
-
url: nonBlankPrompt('The URL, data URL, or file path of this reference image.')
|
|
152
|
-
})).min(1).optional();
|
|
153
|
-
const promptImageConversionInputSchema = v4_namespaceObject.z.boolean().optional().describe('Whether HTTP reference images are converted to base64 first.');
|
|
154
|
-
const aiActOptionsInputSchema = v4_namespaceObject.z.strictObject({
|
|
155
|
-
cacheable: v4_namespaceObject.z.boolean().optional().describe('Whether this action may use the Midscene cache.'),
|
|
156
|
-
fileChooserAccept: v4_namespaceObject.z.union([
|
|
157
|
-
v4_namespaceObject.z.string(),
|
|
158
|
-
v4_namespaceObject.z.array(v4_namespaceObject.z.string())
|
|
159
|
-
]).optional().describe('Accepted file types for a file chooser.'),
|
|
160
|
-
deepThink: v4_namespaceObject.z.union([
|
|
161
|
-
v4_namespaceObject.z.literal('unset'),
|
|
162
|
-
v4_namespaceObject.z.boolean()
|
|
163
|
-
]).optional().describe('Whether to enable deep thinking for this action.'),
|
|
164
|
-
deepLocate: v4_namespaceObject.z.boolean().optional().describe('Whether to use deep element location.'),
|
|
165
|
-
context: v4_namespaceObject.z.string().optional().describe('Additional context supplied to the UI Agent.')
|
|
166
|
-
});
|
|
167
|
-
const aiActInputSchema = v4_namespaceObject.z.strictObject({
|
|
168
|
-
prompt: nonBlankPrompt('The natural-language UI task to perform.'),
|
|
169
|
-
images: promptImagesInputSchema,
|
|
170
|
-
convertHttpImage2Base64: promptImageConversionInputSchema,
|
|
171
|
-
options: aiActOptionsInputSchema.optional()
|
|
172
|
-
});
|
|
173
|
-
const aiAssertOptionsInputSchema = v4_namespaceObject.z.strictObject({
|
|
174
|
-
domIncluded: v4_namespaceObject.z.union([
|
|
175
|
-
v4_namespaceObject.z.boolean(),
|
|
176
|
-
v4_namespaceObject.z.literal('visible-only')
|
|
177
|
-
]).optional().describe('How DOM information is included in the assertion.'),
|
|
178
|
-
screenshotIncluded: v4_namespaceObject.z.boolean().optional().describe('Whether the assertion includes a screenshot.'),
|
|
179
|
-
context: v4_namespaceObject.z.string().optional().describe('Additional context supplied to the UI Agent.')
|
|
180
|
-
});
|
|
181
|
-
const aiAssertInputSchema = v4_namespaceObject.z.strictObject({
|
|
182
|
-
prompt: nonBlankPrompt('The natural-language condition that must be true.'),
|
|
183
|
-
images: promptImagesInputSchema,
|
|
184
|
-
convertHttpImage2Base64: promptImageConversionInputSchema,
|
|
185
|
-
message: v4_namespaceObject.z.string().optional().describe('The assertion failure message.'),
|
|
186
|
-
options: aiAssertOptionsInputSchema.optional()
|
|
187
|
-
});
|
|
188
|
-
const reportScreenshotInputSchema = v4_namespaceObject.z.strictObject({
|
|
189
|
-
base64: v4_namespaceObject.z.string().min(1).describe('A base64-encoded screenshot.'),
|
|
190
|
-
description: v4_namespaceObject.z.string().optional().describe('What the screenshot shows.')
|
|
191
|
-
});
|
|
192
|
-
const recordToReportInputSchema = v4_namespaceObject.z.strictObject({
|
|
193
|
-
prompt: v4_namespaceObject.z.string().optional().describe('String shorthand for the title.'),
|
|
194
|
-
title: v4_namespaceObject.z.string().optional().describe('The report section title.'),
|
|
195
|
-
content: v4_namespaceObject.z.string().optional().describe('The report text content.'),
|
|
196
|
-
screenshotBase64: v4_namespaceObject.z.string().optional().describe('One base64-encoded screenshot.'),
|
|
197
|
-
screenshots: v4_namespaceObject.z.array(reportScreenshotInputSchema).min(1).optional().describe('Screenshots attached to the report section.')
|
|
198
|
-
}).superRefine((input, ctx)=>{
|
|
199
|
-
if (void 0 !== input.prompt && void 0 !== input.title) ctx.addIssue({
|
|
200
|
-
code: 'custom',
|
|
201
|
-
message: 'prompt and title are mutually exclusive'
|
|
202
|
-
});
|
|
203
|
-
if (void 0 !== input.screenshotBase64 && void 0 !== input.screenshots) ctx.addIssue({
|
|
204
|
-
code: 'custom',
|
|
205
|
-
message: 'screenshotBase64 and screenshots are mutually exclusive'
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
const waitInputSchema = v4_namespaceObject.z.strictObject({
|
|
209
|
-
duration: v4_namespaceObject.z.number().positive().describe('How long to wait.'),
|
|
210
|
-
unit: v4_namespaceObject.z["enum"]([
|
|
211
|
-
'ms',
|
|
212
|
-
's',
|
|
213
|
-
'min'
|
|
214
|
-
]).default('ms').describe('Duration unit: milliseconds, seconds, or minutes.')
|
|
215
|
-
});
|
|
216
|
-
const agentInputSchema = v4_namespaceObject.z.strictObject({
|
|
217
|
-
prompt: nonBlankPrompt('A self-contained task, including allowed tools and success conditions.')
|
|
218
|
-
});
|
|
219
|
-
const isRecord = (value)=>'object' == typeof value && null !== value && !Array.isArray(value);
|
|
220
|
-
const requireAgentMethod = (agent, method, node)=>{
|
|
221
|
-
if (!isRecord(agent) || 'function' != typeof agent[method]) throw new NodeExecutionError(node, new TypeError(`getAgent() must return an Agent with ${method}().`));
|
|
222
|
-
return agent[method];
|
|
223
|
-
};
|
|
224
|
-
const maxHistoryContextCharacters = 64000;
|
|
225
|
-
const maxHistoryValuePreviewCharacters = 8000;
|
|
226
|
-
const maxHistoryEntryCharacters = 24000;
|
|
227
|
-
const historyOmissionNoticeReserve = 256;
|
|
228
|
-
const compactHistoryContextValue = (value)=>{
|
|
229
|
-
const serialized = JSON.stringify(value);
|
|
230
|
-
if (void 0 === serialized || serialized.length <= maxHistoryValuePreviewCharacters) return value;
|
|
231
|
-
return {
|
|
232
|
-
omittedFromContext: true,
|
|
233
|
-
originalCharacters: serialized.length,
|
|
234
|
-
preview: 'string' == typeof value ? value.slice(0, maxHistoryValuePreviewCharacters) : serialized.slice(0, maxHistoryValuePreviewCharacters)
|
|
235
123
|
};
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
if (serialized.length <= maxHistoryEntryCharacters) return serialized;
|
|
247
|
-
return JSON.stringify({
|
|
248
|
-
index,
|
|
249
|
-
scope: entry.scope,
|
|
250
|
-
phase: entry.phase,
|
|
251
|
-
stepIndex: entry.stepIndex,
|
|
252
|
-
node: entry.node,
|
|
253
|
-
status: entry.status,
|
|
254
|
-
...void 0 === entry.summary ? {} : {
|
|
255
|
-
summary: compactHistoryContextValue(entry.summary)
|
|
256
|
-
},
|
|
257
|
-
omittedFromContext: true,
|
|
258
|
-
compactedCharacters: serialized.length
|
|
259
|
-
});
|
|
260
|
-
};
|
|
261
|
-
const renderNodeHistory = (history)=>{
|
|
262
|
-
if (0 === history.length) return;
|
|
263
|
-
const heading = 'Previous workflow results (read-only):';
|
|
264
|
-
const availableCharacters = maxHistoryContextCharacters - heading.length - historyOmissionNoticeReserve;
|
|
265
|
-
const renderedEntries = [];
|
|
266
|
-
let renderedCharacters = 0;
|
|
267
|
-
for(let index = history.length - 1; index >= 0; index -= 1){
|
|
268
|
-
const rendered = serializeHistoryEntryForContext(history[index], index + 1);
|
|
269
|
-
const separatorCharacters = 0 === renderedEntries.length ? 0 : 1;
|
|
270
|
-
if (renderedCharacters + separatorCharacters + rendered.length > availableCharacters) break;
|
|
271
|
-
renderedEntries.unshift(rendered);
|
|
272
|
-
renderedCharacters += separatorCharacters + rendered.length;
|
|
273
|
-
}
|
|
274
|
-
const omittedEntries = history.length - renderedEntries.length;
|
|
275
|
-
return [
|
|
276
|
-
heading,
|
|
277
|
-
...0 === omittedEntries ? [] : [
|
|
278
|
-
`${omittedEntries} earlier history entr${1 === omittedEntries ? 'y was' : 'ies were'} omitted from Agent context to stay within the size limit. Complete results remain available in the Test Runner output.`
|
|
279
|
-
],
|
|
280
|
-
...renderedEntries
|
|
281
|
-
].join('\n');
|
|
282
|
-
};
|
|
283
|
-
const mergeContext = (explicit, history)=>[
|
|
284
|
-
explicit,
|
|
285
|
-
renderNodeHistory(history)
|
|
286
|
-
].filter(Boolean).join('\n\n') || void 0;
|
|
287
|
-
const toAgentPrompt = (input)=>{
|
|
288
|
-
if (void 0 === input.images && void 0 === input.convertHttpImage2Base64) return input.prompt;
|
|
289
|
-
return {
|
|
290
|
-
prompt: input.prompt,
|
|
291
|
-
...void 0 === input.images ? {} : {
|
|
292
|
-
images: input.images
|
|
293
|
-
},
|
|
294
|
-
...void 0 === input.convertHttpImage2Base64 ? {} : {
|
|
295
|
-
convertHttpImage2Base64: input.convertHttpImage2Base64
|
|
296
|
-
}
|
|
124
|
+
const validateInputSchema = (schema, node)=>{
|
|
125
|
+
if (void 0 === schema) return;
|
|
126
|
+
if (!(schema instanceof v4_namespaceObject.z.ZodObject)) throw new errors.ww(`Node "${node}" inputSchema must be a Zod object schema.`, {
|
|
127
|
+
node,
|
|
128
|
+
field: 'inputSchema'
|
|
129
|
+
});
|
|
130
|
+
if ('$' in schema.shape) throw new errors.ww(`Node "${node}" inputSchema must not declare "$" as an input property.`, {
|
|
131
|
+
node,
|
|
132
|
+
field: 'inputSchema.$'
|
|
133
|
+
});
|
|
297
134
|
};
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
once: true
|
|
135
|
+
const validateDefinition = (options)=>{
|
|
136
|
+
if (!options || 'object' != typeof options) throw new errors.ww('Node definition must be an object.');
|
|
137
|
+
if ('string' != typeof options.name || 0 === options.name.trim().length) throw new errors.ww('Node name must be a non-empty string.');
|
|
138
|
+
validateOptionalText(options.title, 'title', options.name);
|
|
139
|
+
validateOptionalText(options.description, "description", options.name);
|
|
140
|
+
if (void 0 !== options.stringInputKey && false !== options.stringInputKey && ('string' != typeof options.stringInputKey || 0 === options.stringInputKey.trim().length)) throw new errors.ww(`Node "${options.name}" stringInputKey must be a non-empty string or false.`, {
|
|
141
|
+
node: options.name,
|
|
142
|
+
field: 'stringInputKey'
|
|
143
|
+
});
|
|
144
|
+
validateInputSchema(options.inputSchema, options.name);
|
|
145
|
+
if ('string' == typeof options.stringInputKey && options.inputSchema instanceof v4_namespaceObject.z.ZodObject && !(options.stringInputKey in options.inputSchema.shape)) throw new errors.ww(`Node "${options.name}" stringInputKey must reference a field in inputSchema.`, {
|
|
146
|
+
node: options.name,
|
|
147
|
+
field: 'stringInputKey'
|
|
312
148
|
});
|
|
149
|
+
if ('function' != typeof options.execute) throw new errors.ww(`Node "${options.name}" must provide an execute function.`, {
|
|
150
|
+
node: options.name
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
function defineNode(options) {
|
|
154
|
+
validateDefinition(options);
|
|
155
|
+
return options;
|
|
156
|
+
}
|
|
157
|
+
const nonBlankPrompt = (description)=>v4_namespaceObject.z.string().regex(/\S/, 'prompt must contain a non-whitespace character').describe(description);
|
|
158
|
+
const waitInputSchema = v4_namespaceObject.z.strictObject({
|
|
159
|
+
duration: v4_namespaceObject.z.number().positive().describe('How long to wait.'),
|
|
160
|
+
unit: v4_namespaceObject.z["enum"]([
|
|
161
|
+
'ms',
|
|
162
|
+
's',
|
|
163
|
+
'min'
|
|
164
|
+
]).default('ms').describe('Duration unit: milliseconds, seconds, or minutes.')
|
|
313
165
|
});
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
released.reportPath
|
|
331
|
-
]
|
|
332
|
-
} : void 0;
|
|
333
|
-
} finally{
|
|
334
|
-
registeredAgentScopes.delete(runId);
|
|
335
|
-
}
|
|
166
|
+
const agentInputSchema = v4_namespaceObject.z.strictObject({
|
|
167
|
+
prompt: nonBlankPrompt('A self-contained task, including allowed tools and success conditions.')
|
|
168
|
+
});
|
|
169
|
+
const waitFor = async (durationMs, signal)=>{
|
|
170
|
+
if (signal.aborted) throw signal.reason ?? new Error('Wait aborted.');
|
|
171
|
+
await new Promise((resolve, reject)=>{
|
|
172
|
+
const timeout = setTimeout(()=>{
|
|
173
|
+
signal.removeEventListener('abort', abort);
|
|
174
|
+
resolve();
|
|
175
|
+
}, durationMs);
|
|
176
|
+
const abort = ()=>{
|
|
177
|
+
clearTimeout(timeout);
|
|
178
|
+
reject(signal.reason ?? new Error('Wait aborted.'));
|
|
179
|
+
};
|
|
180
|
+
signal.addEventListener('abort', abort, {
|
|
181
|
+
once: true
|
|
336
182
|
});
|
|
337
|
-
}
|
|
338
|
-
return options.agentProvider.getAgent(runId, ctx);
|
|
183
|
+
});
|
|
339
184
|
};
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const title = ctx.input.title ?? ctx.input.prompt;
|
|
381
|
-
const reportOptions = {
|
|
382
|
-
...void 0 === ctx.input.content ? {} : {
|
|
383
|
-
content: ctx.input.content
|
|
384
|
-
},
|
|
385
|
-
...void 0 === ctx.input.screenshotBase64 ? {} : {
|
|
386
|
-
screenshotBase64: ctx.input.screenshotBase64
|
|
387
|
-
},
|
|
388
|
-
...void 0 === ctx.input.screenshots ? {} : {
|
|
389
|
-
screenshots: ctx.input.screenshots
|
|
185
|
+
const createAgentTestRunnerNodes = (definitions, getAgent)=>definitions.map((definition)=>defineNode({
|
|
186
|
+
name: definition.name,
|
|
187
|
+
...void 0 === definition.title ? {} : {
|
|
188
|
+
title: definition.title
|
|
189
|
+
},
|
|
190
|
+
...void 0 === definition.description ? {} : {
|
|
191
|
+
description: definition.description
|
|
192
|
+
},
|
|
193
|
+
...void 0 === definition.stringInputKey ? {} : {
|
|
194
|
+
stringInputKey: definition.stringInputKey
|
|
195
|
+
},
|
|
196
|
+
inputSchema: definition.inputSchema,
|
|
197
|
+
async execute (ctx) {
|
|
198
|
+
const agent = await getAgent(ctx);
|
|
199
|
+
return definition.execute(agent, ctx.input, {
|
|
200
|
+
signal: ctx.signal
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}));
|
|
204
|
+
function createMidsceneNodes(options) {
|
|
205
|
+
if (!options || 'object' != typeof options) throw new errors.ww('createMidsceneNodes() options must be an object.');
|
|
206
|
+
if ('function' != typeof options.agentProvider?.getAgent && 'function' != typeof options.getAgent) throw new errors.ww('createMidsceneNodes() requires getAgent or agentProvider.getAgent.');
|
|
207
|
+
if (!options.agentClass || 'function' != typeof options.agentClass.getTestRunnerNodeDefinitions) throw new errors.ww('createMidsceneNodes() requires agentClass.getTestRunnerNodeDefinitions().');
|
|
208
|
+
const registeredAgentScopes = new Set();
|
|
209
|
+
const getExecutionId = (ctx)=>'case' === ctx.scope ? ctx.case.runId : ctx.document.documentRunId;
|
|
210
|
+
const getAgent = async (ctx)=>{
|
|
211
|
+
if (!options.agentProvider) return options.getAgent(ctx);
|
|
212
|
+
const runId = getExecutionId(ctx);
|
|
213
|
+
if (options.agentProvider.releaseAgent && !registeredAgentScopes.has(runId)) {
|
|
214
|
+
registeredAgentScopes.add(runId);
|
|
215
|
+
ctx.onTeardown(async ()=>{
|
|
216
|
+
try {
|
|
217
|
+
const released = await options.agentProvider.releaseAgent(runId);
|
|
218
|
+
return released?.reportPath ? {
|
|
219
|
+
reportPaths: [
|
|
220
|
+
released.reportPath
|
|
221
|
+
]
|
|
222
|
+
} : void 0;
|
|
223
|
+
} finally{
|
|
224
|
+
registeredAgentScopes.delete(runId);
|
|
390
225
|
}
|
|
391
|
-
};
|
|
392
|
-
const agent = await getAgent(ctx);
|
|
393
|
-
const recordToReport = requireAgentMethod(agent, 'recordToReport', 'recordToReport');
|
|
394
|
-
await recordToReport.call(agent, title, reportOptions);
|
|
395
|
-
return {
|
|
396
|
-
summary: `Recorded to report: ${title ?? 'untitled'}`
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
}),
|
|
400
|
-
...false === options.includeLaunch ? [] : [
|
|
401
|
-
createLaunchNode(getAgent)
|
|
402
|
-
],
|
|
403
|
-
define_node_defineNode({
|
|
404
|
-
name: 'wait',
|
|
405
|
-
description: 'Wait for a fixed duration while honoring cancellation.',
|
|
406
|
-
inputSchema: waitInputSchema,
|
|
407
|
-
async execute (ctx) {
|
|
408
|
-
const multiplier = 'min' === ctx.input.unit ? 60000 : 's' === ctx.input.unit ? 1000 : 1;
|
|
409
|
-
const durationMs = ctx.input.duration * multiplier;
|
|
410
|
-
await waitFor(durationMs, ctx.signal);
|
|
411
|
-
return {
|
|
412
|
-
summary: `Waited ${durationMs}ms`
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
}),
|
|
416
|
-
define_node_defineNode({
|
|
417
|
-
name: 'agent',
|
|
418
|
-
description: 'Execute one self-contained natural-language task with an injected Agent executor.',
|
|
419
|
-
inputSchema: agentInputSchema,
|
|
420
|
-
async execute (ctx) {
|
|
421
|
-
if (!options.agentExecutor) throw new NodeExecutionError('agent', new TypeError('createMidsceneNodes() requires an agentExecutor.'));
|
|
422
|
-
const execution = 'case' === ctx.scope ? {
|
|
423
|
-
scope: 'case',
|
|
424
|
-
runId: ctx.case.runId
|
|
425
|
-
} : {
|
|
426
|
-
scope: 'document',
|
|
427
|
-
runId: ctx.document.documentRunId
|
|
428
|
-
};
|
|
429
|
-
const result = await options.agentExecutor.execute({
|
|
430
|
-
prompt: ctx.input.prompt,
|
|
431
|
-
history: ctx.history,
|
|
432
|
-
context: ctx.context,
|
|
433
|
-
signal: ctx.signal,
|
|
434
|
-
execution
|
|
435
226
|
});
|
|
436
|
-
return result ?? {
|
|
437
|
-
summary: 'Agent task completed.'
|
|
438
|
-
};
|
|
439
227
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
228
|
+
return options.agentProvider.getAgent(runId, ctx);
|
|
229
|
+
};
|
|
230
|
+
const agentDefinitions = options.agentClass.getTestRunnerNodeDefinitions();
|
|
231
|
+
return [
|
|
232
|
+
...createAgentTestRunnerNodes(agentDefinitions, getAgent),
|
|
233
|
+
defineNode({
|
|
234
|
+
name: 'wait',
|
|
235
|
+
description: 'Wait for a fixed duration while honoring cancellation.',
|
|
236
|
+
stringInputKey: false,
|
|
237
|
+
inputSchema: waitInputSchema,
|
|
238
|
+
async execute (ctx) {
|
|
239
|
+
const multiplier = 'min' === ctx.input.unit ? 60000 : 's' === ctx.input.unit ? 1000 : 1;
|
|
240
|
+
const durationMs = ctx.input.duration * multiplier;
|
|
241
|
+
await waitFor(durationMs, ctx.signal);
|
|
242
|
+
return {
|
|
243
|
+
summary: `Waited ${durationMs}ms`
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}),
|
|
247
|
+
defineNode({
|
|
248
|
+
name: 'agent',
|
|
249
|
+
description: 'Execute one self-contained natural-language task with an injected Agent executor.',
|
|
250
|
+
stringInputKey: 'prompt',
|
|
251
|
+
inputSchema: agentInputSchema,
|
|
252
|
+
async execute (ctx) {
|
|
253
|
+
if (!options.agentExecutor) throw new errors.h2('agent', new TypeError('createMidsceneNodes() requires an agentExecutor.'));
|
|
254
|
+
const execution = 'case' === ctx.scope ? {
|
|
255
|
+
scope: 'case',
|
|
256
|
+
runId: ctx.case.runId
|
|
257
|
+
} : {
|
|
258
|
+
scope: 'document',
|
|
259
|
+
runId: ctx.document.documentRunId
|
|
260
|
+
};
|
|
261
|
+
const result = await options.agentExecutor.execute({
|
|
262
|
+
prompt: ctx.input.prompt,
|
|
263
|
+
context: ctx.context,
|
|
264
|
+
signal: ctx.signal,
|
|
265
|
+
execution
|
|
266
|
+
});
|
|
267
|
+
return result ?? {
|
|
268
|
+
summary: 'Agent task completed.'
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
})
|
|
272
|
+
];
|
|
273
|
+
}
|
|
274
|
+
})();
|
|
443
275
|
exports.agentInputSchema = __webpack_exports__.agentInputSchema;
|
|
444
276
|
exports.aiActInputSchema = __webpack_exports__.aiActInputSchema;
|
|
277
|
+
exports.aiActOptionsInputSchema = __webpack_exports__.aiActOptionsInputSchema;
|
|
445
278
|
exports.aiAssertInputSchema = __webpack_exports__.aiAssertInputSchema;
|
|
279
|
+
exports.aiAssertOptionsInputSchema = __webpack_exports__.aiAssertOptionsInputSchema;
|
|
280
|
+
exports.aiTapInputSchema = __webpack_exports__.aiTapInputSchema;
|
|
281
|
+
exports.createAgentTestRunnerNodes = __webpack_exports__.createAgentTestRunnerNodes;
|
|
446
282
|
exports.createMidsceneNodes = __webpack_exports__.createMidsceneNodes;
|
|
447
|
-
exports.
|
|
283
|
+
exports.insightInputSchema = __webpack_exports__.insightInputSchema;
|
|
284
|
+
exports.insightOptionsInputSchema = __webpack_exports__.insightOptionsInputSchema;
|
|
285
|
+
exports.locateOptionsInputSchema = __webpack_exports__.locateOptionsInputSchema;
|
|
286
|
+
exports.promptImageInputSchema = __webpack_exports__.promptImageInputSchema;
|
|
448
287
|
exports.recordToReportInputSchema = __webpack_exports__.recordToReportInputSchema;
|
|
449
|
-
exports.
|
|
288
|
+
exports.recordToReportOptionsInputSchema = __webpack_exports__.recordToReportOptionsInputSchema;
|
|
289
|
+
exports.reportScreenshotInputSchema = __webpack_exports__.reportScreenshotInputSchema;
|
|
290
|
+
exports.structuredUserPromptInputSchema = __webpack_exports__.structuredUserPromptInputSchema;
|
|
291
|
+
exports.userPromptInputSchema = __webpack_exports__.userPromptInputSchema;
|
|
450
292
|
exports.waitInputSchema = __webpack_exports__.waitInputSchema;
|
|
451
293
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
452
294
|
"agentInputSchema",
|
|
453
295
|
"aiActInputSchema",
|
|
296
|
+
"aiActOptionsInputSchema",
|
|
454
297
|
"aiAssertInputSchema",
|
|
298
|
+
"aiAssertOptionsInputSchema",
|
|
299
|
+
"aiTapInputSchema",
|
|
300
|
+
"createAgentTestRunnerNodes",
|
|
455
301
|
"createMidsceneNodes",
|
|
456
|
-
"
|
|
302
|
+
"insightInputSchema",
|
|
303
|
+
"insightOptionsInputSchema",
|
|
304
|
+
"locateOptionsInputSchema",
|
|
305
|
+
"promptImageInputSchema",
|
|
457
306
|
"recordToReportInputSchema",
|
|
458
|
-
"
|
|
307
|
+
"recordToReportOptionsInputSchema",
|
|
308
|
+
"reportScreenshotInputSchema",
|
|
309
|
+
"structuredUserPromptInputSchema",
|
|
310
|
+
"userPromptInputSchema",
|
|
459
311
|
"waitInputSchema"
|
|
460
312
|
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
461
313
|
Object.defineProperty(exports, '__esModule', {
|